背景:我必须编写一个应用程序,该应用程序使用一个设计不良的EBCDIC文件,其中包含使用ASCII行终止符的二进制数据,并且有时二进制数据碰巧包含ASCII CRLF,这会导致行错误地分割。我需要采用这种旧文件格式,并在每条记录的末尾删除CRLF。
似乎使用StreamReader
withIBM037
编码会导致该ReadLine()
方法只读取\r
到行尾,而不是\r\n
我期望的那样,因此,我从ReadLine
LF(0A
以ASCII开头)开头的每个字符串(在第一个字符串之后)都会返回。
重现此问题的示例程序:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
class Program
{
static void Main(string[] args)
{
//generate example EBCDIC data
List<byte> bytes = new List<byte>();
Encoding EBCDIC = Encoding.GetEncoding("IBM037");
bytes.AddRange(Encoding.Convert(Encoding.ASCII, EBCDIC, Encoding.ASCII.GetBytes("Some nice ascii text")));
bytes.AddRange(new byte[] { (byte)'\r', (byte)'\n' });
bytes.AddRange(Encoding.Convert(Encoding.ASCII, EBCDIC, Encoding.ASCII.GetBytes("Some more nice ascii text")));
//read it using StreamReader
using(MemoryStream ms = new MemoryStream(bytes.ToArray()))
using (StreamReader reader = new StreamReader(ms, EBCDIC))
{
string line = string.Empty;
while ((line = reader.ReadLine()) != null)
{
EBCDIC.GetBytes(line).ToList().ForEach(c => Console.Write(c));
Console.WriteLine();
}
}
Console.ReadLine();
}
}
输出应如下所示:
226150148133641491371311336412916213113713764163133167163
1022615014813364148150153133641491371311336412916213113713764163133167163
第二行开头的10应该不存在,因为那是CRLF序列中的LF。
我对ReadLine
方法的理解是:
一行定义为一系列字符,后跟换行符(“ \ n”),回车符(“ \ r”)或回车符后紧跟换行符(“ \ r \ n”)。返回的字符串不包含终止回车符或换行符。来源
它没有说改变编码的任何内容,因此据此它应该读取我数据中的完整CRLF,而不仅仅是CR。
更新:我已经解决了这个问题,并实现了自己的读取数据的方法,但是我的问题仍然如下:为什么ReadLine
不听锡说什么?
您将(byte)'\r'
和填充(byte)'\n'
到一个流中,并告诉该流StreamReader
已用EBCDIC编码。
的值为(byte) '\r'
0x0d,碰巧是ASCII和EBCDIC中的回车符。
的值为(byte) '\n'
0x0a,它是ASCII中的换行符,但不是EBCDIC中的换行符。
如果您查看EBCDIC Encoder类如何将值0x0a解码为.NET Unicodechar
类型,则会发现Unicode的数字值为char
142(或0x8e)。而且该字符不是换行符。(我不知道为什么将其解码为142)。
您会在第二行的开头看到输出“ 10”的原因,不是因为那里有换行,而是因为值142的char被重新编码回值为10的EBCDIC字节(在子表达式中EBCDIC.GetBytes(line)
) 。
因此,很简单地回答您的问题,ReadLine()
只会看到回车,而不是回车后跟换行符。
将while
循环更改为如下所示:
while ((line = reader.ReadLine()) != null)
{
line.ToList().ForEach(c => { Console.Write(c); Console.Write(" "); });
Console.WriteLine();
line.ToList().ForEach(c => { Console.Write(Convert.ToInt32(c)); Console.Write(" "); });
Console.WriteLine();
EBCDIC.GetBytes(line).ToList().ForEach(c => { Console.Write(c); Console.Write(" "); });
Console.WriteLine();
Console.WriteLine();
Console.WriteLine();
}
您将在第二行中获得以下输出,该行显示(从EBCDIC转换为)字符的行,这些字符的Unicode值,最后将这些字符的值转换回EBCDIC:
? S o m e m o r e n i c e a s c i i t e x t
142 83 111 109 101 32 109 111 114 101 32 110 105 99 101 32 97 115 99 105 105 32 116 101 120 116
10 226 150 148 133 64 148 150 153 133 64 149 137 131 133 64 129 162 131 137 137 64 163 133 167 163
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句