ฉันต้องเขียนการทดสอบหน่วยสำหรับวิธีที่ใช้กระแสซึ่งมาจากไฟล์ข้อความ ฉันต้องการทำสิ่งนี้:
Stream s = GenerateStreamFromString("a,b \n c,d");
ฉันต้องเขียนการทดสอบหน่วยสำหรับวิธีที่ใช้กระแสซึ่งมาจากไฟล์ข้อความ ฉันต้องการทำสิ่งนี้:
Stream s = GenerateStreamFromString("a,b \n c,d");
คำตอบ:
public static Stream GenerateStreamFromString(string s)
{
var stream = new MemoryStream();
var writer = new StreamWriter(stream);
writer.Write(s);
writer.Flush();
stream.Position = 0;
return stream;
}
อย่าลืมที่จะใช้การใช้:
using (var stream = GenerateStreamFromString("a,b \n c,d"))
{
// ... Do stuff to stream
}
เกี่ยวกับการStreamWriter
ไม่ถูกกำจัด StreamWriter
เป็นเพียงเสื้อคลุมรอบสตรีมพื้นฐานและไม่ใช้ทรัพยากรใด ๆ ที่จำเป็นต้องกำจัด Dispose
วิธีการจะปิดพื้นฐานStream
ที่StreamWriter
จะเขียนถึง ในกรณีนี้คือสิ่งที่MemoryStream
เราต้องการคืน
ใน. NET 4.5 ขณะนี้มีการโอเวอร์โหลดสำหรับStreamWriter
การเปิดกระแสข้อมูลพื้นฐานหลังจากที่ผู้เขียนถูกกำจัด แต่รหัสนี้ทำสิ่งเดียวกันและทำงานร่วมกับ. NET รุ่นอื่นด้วย
GenerateStreamFromString
วิธีการของคุณคุณไม่ได้ใช้การใช้กับ StreamWriter มีเหตุผลสำหรับสิ่งนี้หรือไม่?
StreamWriter
อาจทำในสิ่งที่คุณพูดภายใน ข้อดีคือ encapsulation และรหัสที่ง่ายกว่า แต่มีค่าใช้จ่ายในการสรุปสิ่งต่าง ๆ เช่นการเข้ารหัสออกไป ขึ้นอยู่กับสิ่งที่คุณพยายามทำ
ทางออกอื่น:
public static MemoryStream GenerateStreamFromString(string value)
{
return new MemoryStream(Encoding.UTF8.GetBytes(value ?? ""));
}
new MemoryStream(Encoding.UTF8.GetBytes("\ufeff" + (value ?? ""))
ถ้าคุณต้องการให้ BOM รวมไว้ที่จุดเริ่มต้นของสตรีม
new MemoryStream( value, false )
. คุณไม่สามารถสร้างสตรีมแบบอ่านอย่างเดียวได้หากคุณต้องเขียนด้วยสตรีมตัวเขียน
เพิ่มสิ่งนี้ไปยังคลาสยูทิลิตี้สตริงคงที่:
public static Stream ToStream(this string str)
{
MemoryStream stream = new MemoryStream();
StreamWriter writer = new StreamWriter(stream);
writer.Write(str);
writer.Flush();
stream.Position = 0;
return stream;
}
นี่เป็นการเพิ่มฟังก์ชั่นเสริมเพื่อให้คุณสามารถ:
using (var stringStream = "My string".ToStream())
{
// use stringStream
}
StreamWriter
เมื่อเก็บขยะทำความสะอาดขึ้น การแก้ไขคือการใช้ตัวสร้างที่แตกต่างกัน - หนึ่งที่อนุญาตให้ฉันไประบุleaveOpen
public Stream GenerateStreamFromString(string s)
{
return new MemoryStream(Encoding.UTF8.GetBytes(s));
}
ใช้MemoryStream
คลาสโทรEncoding.GetBytes
เพื่อเปลี่ยนสตริงของคุณให้เป็นอาร์เรย์ไบต์ก่อน
คุณจำเป็นต้องมีTextReader
สตรีมในภายหลังหรือไม่? ถ้าเป็นเช่นนั้นคุณสามารถจัดหาStringReader
โดยตรงและข้ามMemoryStream
และEncoding
ขั้นตอน
ฉันใช้คำตอบแบบผสม:
public static Stream ToStream(this string str, Encoding enc = null)
{
enc = enc ?? Encoding.UTF8;
return new MemoryStream(enc.GetBytes(str ?? ""));
}
แล้วฉันจะใช้มันเช่นนี้
String someStr="This is a Test";
Encoding enc = getEncodingFromSomeWhere();
using (Stream stream = someStr.ToStream(enc))
{
// Do something with the stream....
}
เราใช้วิธีการขยายที่แสดงด้านล่าง ฉันคิดว่าคุณควรให้นักพัฒนาตัดสินใจเกี่ยวกับการเข้ารหัสดังนั้นจึงมีเวทมนตร์น้อยลง
public static class StringExtensions {
public static Stream ToStream(this string s) {
return s.ToStream(Encoding.UTF8);
}
public static Stream ToStream(this string s, Encoding encoding) {
return new MemoryStream(encoding.GetBytes(s ?? ""));
}
}
return ToStream(s, Encoding.UTF8);
ฉันชอบที่จะใช้วิธีแรกเป็น ในการดำเนินการปัจจุบัน ( return s.ToStream(Encoding.UTF8);
นักพัฒนาที่ถูกบังคับให้ต้องคิดยากที่จะเข้าใจรหัสและดูเหมือนว่ากรณีที่s == null
เป็นไม่สามารถจัดการได้และพ่นNullReferenceException
.
ไปเลย:
private Stream GenerateStreamFromString(String p)
{
Byte[] bytes = UTF8Encoding.GetBytes(p);
MemoryStream strm = new MemoryStream();
strm.Write(bytes, 0, bytes.Length);
return strm;
}
วิธีการขยายรุ่นที่ทันสมัยและแก้ไขเล็กน้อยสำหรับToStream
:
public static Stream ToStream(this string value) => ToStream(value, Encoding.UTF8);
public static Stream ToStream(this string value, Encoding encoding)
=> new MemoryStream(encoding.GetBytes(value ?? string.Empty));
การแก้ไขตามที่แนะนำไว้ในความคิดเห็นของ @ Palec ของคำตอบ @Shaun Bowe
ฉันคิดว่าคุณสามารถได้รับประโยชน์จากการใช้MemoryStream คุณสามารถกรอกด้วยสตริงไบต์ที่คุณได้รับโดยใช้GetBytesวิธีการระดับการเข้ารหัส
หากคุณต้องการเปลี่ยนการเข้ารหัสฉันลงคะแนนให้โซลูชันของ@ShaunBowe แต่ทุกคำตอบที่นี่คัดลอกสตริงทั้งหมดในหน่วยความจำอย่างน้อยหนึ่งครั้ง คำตอบด้วยToCharArray
+ BlockCopy
คอมโบทำได้สองครั้ง
หากสิ่งที่สำคัญตรงนี้เป็นStream
เครื่องห่อหุ้มอย่างง่ายสำหรับสตริง raw UTF-16 หากใช้กับตัวStreamReader
เลือกEncoding.Unicode
:
public class StringStream : Stream
{
private readonly string str;
public override bool CanRead => true;
public override bool CanSeek => true;
public override bool CanWrite => false;
public override long Length => str.Length * 2;
public override long Position { get; set; } // TODO: bounds check
public StringStream(string s) => str = s ?? throw new ArgumentNullException(nameof(s));
public override long Seek(long offset, SeekOrigin origin)
{
switch (origin)
{
case SeekOrigin.Begin:
Position = offset;
break;
case SeekOrigin.Current:
Position += offset;
break;
case SeekOrigin.End:
Position = Length - offset;
break;
}
return Position;
}
private byte this[int i] => (i & 1) == 0 ? (byte)(str[i / 2] & 0xFF) : (byte)(str[i / 2] >> 8);
public override int Read(byte[] buffer, int offset, int count)
{
// TODO: bounds check
var len = Math.Min(count, Length - Position);
for (int i = 0; i < len; i++)
buffer[offset++] = this[(int)(Position++)];
return (int)len;
}
public override int ReadByte() => Position >= Length ? -1 : this[(int)Position++];
public override void Flush() { }
public override void SetLength(long value) => throw new NotSupportedException();
public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException();
public override string ToString() => str; // ;)
}
และนี่คือโซลูชันที่สมบูรณ์ยิ่งขึ้นด้วยการตรวจสอบขอบเขตที่จำเป็น (ซึ่งได้มาจากMemoryStream
มันToArray
และWriteTo
วิธีการเช่นกัน)
การรวมกันที่ดีของส่วนขยายของสตริง:
public static byte[] GetBytes(this string str)
{
byte[] bytes = new byte[str.Length * sizeof(char)];
System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
return bytes;
}
public static Stream ToStream(this string str)
{
Stream StringStream = new MemoryStream();
StringStream.Read(str.GetBytes(), 0, str.Length);
return StringStream;
}
StringReaderStream
ในstackoverflow.com/a/55170901/254109