using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Runtime.InteropServices; namespace miew.IO { using String = System.String; public static class File { static public String Read(string szfile) { String ret = String.Empty; try { using (FileStream fs = System.IO.File.Open(szfile, FileMode.Open, FileAccess.Read, FileShare.Read)) { // ?? manually detect BOM, because can't seem to set default encoding to 874 using 'detect from BOM' feature of StreamReader constructor byte[] BOM = new byte[4]; fs.Read(BOM, 0, 4); fs.Seek(0, SeekOrigin.Begin); if ((BOM[0] == 0xef && BOM[1] == 0xbb && BOM[2] == 0xbf) || // UTF-8 (BOM[0] == 0xFE && BOM[1] == 0xFF) || // Unicode (Big-Endian) (BOM[0] == 0xFF && BOM[1] == 0xFE) || // Unicode (Little-Endian) (BOM[0] == 0 && BOM[1] == 0 && BOM[2] == 0xfe && BOM[3] == 0xff) || // UTF-32 (BOM[0] == 0x2b && BOM[1] == 0x2f && BOM[2] == 0x76)) // UTF-7 { using (StreamReader sr = new StreamReader(fs, true)) // (auto-detect BOM) ret = sr.ReadToEnd(); } else using (StreamReader sr = new StreamReader(fs /*, Encoding.Default */)) ret = sr.ReadToEnd(); } } catch (FileNotFoundException fnf) { Console.WriteLine("File not found: {0}", fnf.FileName); Environment.Exit(1); } return ret; } /// <summary> /// Case-insensitive search for a file /// </summary> static public String CaseInsensitiveFilename(String s_dir, String file) { return Directory.EnumerateFiles(s_dir, "*", SearchOption.TopDirectoryOnly) .FirstOrDefault(f => Path.GetFileName(f).ToLower() == file); } }; public static class Extensions { /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public static IEnumerable<String> Lines(this TextReader tr) { String l; while ((l = tr.ReadLine()) != null) yield return l; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public static Guid ReadGuid(this BinaryReader br) { return new Guid(br.ReadBytes(16)); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Forces unicode encoding, as opposed to the BinaryReader default /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public static String ReadUnicodeString(this BinaryReader br) { ushort cch = br.ReadUInt16(); if (cch == 0) return String.Empty; return new String(br.ReadChars(cch)); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public static DateTime ReadSystemTime(this BinaryReader br) { return DateTime.FromBinary(br.ReadInt64()); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public static void Write(this BinaryWriter bw, Guid guid) { bw.Write(guid.ToByteArray()); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public static void WriteUnicodeString(this BinaryWriter bw, String s) { if (String.IsNullOrEmpty(s)) { bw.Write((ushort)0); return; } bw.Write((ushort)s.Length); bw.Write(s.ToCharArray(), 0, s.Length); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public static void Write(this BinaryWriter bw, DateTime dt) { bw.Write(dt.ToBinary()); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public static void Write67EncodedUint(this BinaryWriter bw, uint i) { if (miew.BitArray.Extensions.OnesCount(i) == 1) { bw.Write((byte)(0x80 | miew.BitArray.Extensions.OnlyBitPosition(i))); } else { byte b = (byte)(i & 0x3F); i >>= 6; if (i == 0) bw.Write(b); else { bw.Write((byte)(0x40 | b)); while (true) { b = (byte)(i & 0x7F); i >>= 7; if (i == 0) { bw.Write(b); break; } bw.Write((byte)(0x80 | b)); } } } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public static uint Read67EncodedUint(this BinaryReader br) { byte b = br.ReadByte(); if ((b & 0x80) > 0) return (uint)1 << (b & 0x1F); uint i = (uint)(b & 0x3F); if ((b & 0x40) == 0) return i; int r = 6; while (true) { b = br.ReadByte(); i |= (uint)(b & 0x7F) << r; if ((b & 0x80) == 0) return i; r += 7; } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Write the specified thin string to the memory stream /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public static void WriteStringAsByteArr(this MemoryStream ms, String thin) { Byte[] buf = miew.String.Thin.Extensions.ToByteArr(thin); ms.Write(buf); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Image a portion of the specified string to the memory stream in little-endian Unicode byte order, /// without creating an intermediate string object. However, Stringbuilder(String, int, int) is faster than this. /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public static unsafe void Write(this MemoryStream ms, String s, int index, int length) { if (index < 0 || index + length >= s.Length) throw new ArgumentException(); long idx = ms.Position; int cb = length * sizeof(Char); ms.Position = idx + cb; ms.SetLength(ms.Position); fixed (Char* p = s) { IntPtr ip = new IntPtr(p + index); Marshal.Copy(ip, ms.GetBuffer(), (int)idx, cb); } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public static void Write(this Stream str, Byte[] buf) { str.Write(buf, 0, buf.Length); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public static void AlignQword(this Stream str) { long pos = str.Position; long p2 = (pos + 7) & ~7; if (p2 != pos) { if (str.Length <= p2) str.Write(new byte[8 - (pos & 7)]); else str.Seek(p2, SeekOrigin.Begin); } } } }