private void CopySection() { // Console.WriteLine("first = " + firstSource + ":" + startPosition + " last = " + lastSource + ":" + endPosition); try { if (textMode) { //Console.WriteLine(">> first = " + firstSource + ":" + startPosition + " last = " + lastSource + ":" + endPosition); char[] buf = new char[256 * 1024]; int c; using (StreamWriter d = ZStreamWriter.Open(dest)) { // First file: Encoding enc = null; if (startPosition == 0) { startMutex.Set(); } else { using (StreamReader s = ZStreamReader.Open(source[firstSource])) { s.Read(); enc = s.CurrentEncoding; } //if (enc is UnicodeEncoding) //{ // // what about endianness? *** // enc = UTF16Raw.UTF16; //} byte[] preamble = enc.GetPreamble(); if (preamble != null && preamble.Length != 0) { enc = new NoPreambleEncoding(enc); } } //using (PositionStreamReader s = new PositionStreamReader( // ZStreamIn.Open(source[firstSource]))) //{ // while ((line = s.ReadLine()) != null) // { // if (s.Position >= startPosition) break; // d.WriteLine(line); // } // while ((line = s.ReadLine()) != null) // { // d.WriteLine(line); // if (firstSource == lastSource && s.Position > endPosition) break; // } //} using (Stream ss = ZStreamIn.Open(source[firstSource])) { bool done = false; // find the start (next newline after specified): if (startPosition != 0) { ss.Seek(startPosition, SeekOrigin.Begin); int b = ss.ReadByte(); for (; b >= 0 && b != '\n'; b = ss.ReadByte()) { } if (b < 0) { done = true; startPosition = long.MaxValue; } else { startPosition = ss.Position; } startMutex.Set(); } //Console.WriteLine("start: " + firstSource + ":" + ss.Position); if (!done) { long len = ss.Length; //bool newlineTerminate = false; Stream sss = ss; if (firstSource < lastSource || endPosition == long.MaxValue || endPosition < 0 || (len >= 0 && endPosition >= len)) { // write the whole file until the end: //newlineTerminate = true; } else { // need to get the end correctly!! From the next reader?? ****** if (next != null) { endPosition = next.TrueStart; } sss = new BoundedStream(ss, ss.Position, endPosition); //Console.WriteLine("end: " + firstSource + ":" + endPosition); } using (StreamReader s = startPosition == 0 ? new StreamReader(sss) : new StreamReader(sss, enc, false)) { c = s.Read(buf, 0, buf.Length); if (c > 0) { int lastC = c; d.Write(buf, 0, c); while ((c = s.Read(buf, 0, buf.Length)) > 0) { d.Write(buf, 0, c); lastC = c; } if (buf[lastC - 1] != '\n') { // file didn't end in a newline - add one in! // but newlines are no longer converted without ReadLine/WriteLine! *** //Console.Error.WriteLine("no newline!!! 1"); d.WriteLine(); } } } } } // Remaining files: if (firstSource < lastSource) { int lastFullSource = lastSource; if (endPosition != long.MaxValue && endPosition >= 0) { lastFullSource--; } // Full files: for (int i = firstSource + 1; i <= lastFullSource; i++) { using (StreamReader s = ZStreamReader.Open(source[i])) { //while ((line = s.ReadLine()) != null) //{ // d.WriteLine(line); //} c = s.Read(buf, 0, buf.Length); if (c > 0) { int lastC = c; d.Write(buf, 0, c); while ((c = s.Read(buf, 0, buf.Length)) > 0) { d.Write(buf, 0, c); lastC = c; } if (buf[lastC - 1] != '\n') { // file didn't end in a newline - add one in! // but newlines are no longer converted without ReadLine/WriteLine! *** //Console.Error.WriteLine("no newline!!! 2"); d.WriteLine(); } } } } // Last file: //if (last != lastSource) //{ //using (PositionStreamReader s = new PositionStreamReader( // ZStreamIn.Open(source[lastSource]))) //{ // while ((line = s.ReadLine()) != null) // { // d.WriteLine(line); // if (s.Position > endPosition) break; // } //} if (lastFullSource != lastSource) { using (Stream ss = ZStreamIn.Open(source[lastSource])) { // need to get the end correctly!! From the next reader?? ****** long len = ss.Length; Stream sss = ss; if (len >= 0 && endPosition >= len) { // write the whole file until the end: //newlineTerminate = true; } else { // need to get the end correctly!! From the next reader?? ****** if (next != null) { endPosition = next.TrueStart; } sss = new BoundedStream(ss, 0, endPosition); //Console.WriteLine("end: " + firstSource + ":" + endPosition); } using (StreamReader s = new StreamReader(sss)) { c = s.Read(buf, 0, buf.Length); if (c > 0) { int lastC = c; d.Write(buf, 0, c); while ((c = s.Read(buf, 0, buf.Length)) > 0) { d.Write(buf, 0, c); lastC = c; } if (buf[lastC - 1] != '\n') { // file didn't end in a newline - add one in! // but newlines are no longer converted without ReadLine/WriteLine! *** // this one should never happen... //Console.Error.WriteLine("no newline!!! 3"); d.WriteLine(); } } } } } } } } else { //using (Stream d = ZStreamOut.Open(dest)) using (Stream d = new CosmosWriteStream(dest, false, breakAtLines)) { byte[] buf = new byte[256 * 1024]; int count; for (int i = firstSource; i <= lastSource; i++) { using (Stream s = ZStreamIn.Open(source[i])) //using (Stream s = new BufferedStream(ZStreamIn.Open(source[i]), 8*1024*1024)) { if (i == firstSource && startPosition != 0) { s.Seek(startPosition, SeekOrigin.Begin); } if (i == lastSource && endPosition >= 0 && endPosition < long.MaxValue) { long total = startPosition; int limit = buf.Length; if (total + limit > endPosition) { limit = (int)(endPosition - total); } while (total < endPosition && (count = s.Read(buf, 0, limit)) > 0) { d.Write(buf, 0, count); total += count; // > ? or >=? if (total + limit > endPosition) { limit = (int)(endPosition - total); } } } else { while ((count = s.Read(buf, 0, buf.Length)) > 0) { d.Write(buf, 0, count); } } } } } } Console.WriteLine("<< first = " + firstSource + ":" + startPosition + " last = " + lastSource + ":" + endPosition); } catch { try { Delete(dest); } catch { } hasError = true; } }
private static void Append(string source, string destination, bool retryNoExist) { if (source == destination) { throw new IOException("Could not append '" + source + "' to itself"); } //if (!Cosmos.FileExists(destination)) //{ // Console.WriteLine("Copy(" + source + ", " + destination + ")..."); // Copy(source, destination); // Console.WriteLine(" (" + source + ", " + destination + ")."); // return; //} System.Diagnostics.Process proc = null; try { //Console.WriteLine("Executing cosmos " + string.Format(cosmosAppendCmdArgs, source, destination)); proc = Cosmos.CosmosExec(string.Format(Cosmos.cosmosAppendCmdArgs, source, destination)); using (StreamReader sr = proc.StandardOutput) { try { sr.ReadToEnd(); proc.WaitForExit(); } catch { // ignore... } } if (proc.ExitCode != 0) { //Console.WriteLine("bad exit code: " + proc.ExitCode); throw new Exception(); } } catch { if (proc != null) { proc.Close(); proc = null; } if (!Cosmos.FileExists(destination)) { //Console.WriteLine("Copy(" + source + ", " + destination + ")..."); //Copy(source, destination); //Console.WriteLine(" (" + source + ", " + destination + ")."); if (retryNoExist) { // make sure the file is written... using (Stream os = new CosmosWriteStream(destination)) { } // should be 0 bytes. // hopefully, no infinite loop here: Append(source, destination, false); return; } else { try { DeleteFile(destination); } catch { } throw new IOException("Could not append '" + source + "' to '" + destination + "'"); } } else if (Cosmos.GetLength(source) == 0) { // nothing to do, then... return; } throw new IOException("Could not append '" + source + "' to '" + destination + "'"); } finally { if (proc != null) { proc.Close(); } } }
/// <summary> /// Create a Cosmos stream that is the concatenation of other Cosmos streams. /// </summary> /// <remarks> /// <p> /// This should be an efficient operation, but it will leave the trailing extents incomplete. /// </p> /// <p> /// Wildcard patterns are allowed. /// </p> /// </remarks> /// <param name="sources">the name of the streams to concatenate</param> /// <param name="destination">the name of the stream to create</param> /// <exception cref="IOException">The concatenation could not be completed.</exception> /// <exception cref="ArgumentException">Some sources are not cosmos stream names.</exception> public static void Concatenate(string destination, params string[] sources) { //Console.WriteLine("Join:"); if (sources == null) sources = new string[0]; ArrayList expanded = null; for (int i = 0; i < sources.Length; i++) { if (sources[i] == null || string.Compare(sources[i], 0, "cosmos://", 0, "cosmos://".Length, true) != 0) { throw new ArgumentException("Source is not a Cosmos stream name: " + sources[i], "sources"); } if (sources[i].IndexOf('*') >= 0 || sources[i].IndexOf('?') >= 0 || sources[i].IndexOf("...") >= 0) { if (expanded == null) { expanded = new ArrayList(); for (int j = 0; j < i; j++) { expanded.Add(sources[j]); } } // should share batch process: *** expanded.AddRange(IOUtil.ExpandWildcards(sources[i])); } else { if (expanded != null) expanded.Add(sources[i]); } } if (expanded != null) { sources = (string[])expanded.ToArray(typeof(string)); } //for (int i = 0; i < sources.Length; i++) //{ // if (!Cosmos.FileExists(sources[i])) // { // throw new IOException("Cosmos stream to join not found: " + sources[i]); // } //} //Console.WriteLine("Join:Exists"); //Overwrite(destination, false); try { // should share batch process: *** DeleteFile(destination); } catch { // ignore } // make sure the file is written... using (Stream os = new CosmosWriteStream(destination)) { } // should be 0 bytes. //Console.WriteLine("Join:Init[" + sources.Length + "]"); for (int i = 0; i < sources.Length; i++) { string source = sources[i]; try { //Console.Write("."); // should share batch process: *** Append(source, destination); //Console.Write(","); } catch { try { // should share batch process: *** DeleteFile(destination); } catch { // ignore } throw new IOException("Could not concatenate '" + source + "' to '" + destination + "'"); } } //Console.WriteLine("Join:Done."); }
/// <summary> /// Create a Cosmos directory. /// </summary> /// <param name="path">the directory name to create</param> /// <exception cref="IOException">The directory cannot be created.</exception> public static void CreateDirectory(string path) { if (path == null || path.Length == 0) throw new IOException("Cannot create directory for empty path"); path = path.Replace('\\', '/'); try { if (path[path.Length - 1] != '/') path = path + "/"; using (CosmosWriteStream cw = new CosmosWriteStream(path + ".dir")) { cw.Flush(); cw.Close(); } } catch { } }