我正在尝试从磁盘读取大文件并在加载时报告百分比.问题是FileInfo.Length报告的大小不同于我的Encoding.ASCII.GetBytes().长度.
public void loadList()
{
string ListPath = InnerConfig.dataDirectory + core.operation[operationID].Operation.Trim() + "/List.txt";
FileInfo f = new FileInfo(ListPath);
int bytesLoaded = 0;
using (FileStream fs = File.Open(ListPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (BufferedStream bs = new BufferedStream(fs))
using (StreamReader sr = new StreamReader(bs))
{
string line;
while ((line = sr.ReadLine()) != null)
{
byte[] array = Encoding.ASCII.GetBytes(line);
bytesLoaded += array.Length;
}
}
MessageBox.Show(bytesLoaded + "/" + f.Length);
}
Run Code Online (Sandbox Code Playgroud)
结果是
13357/15251
Run Code Online (Sandbox Code Playgroud)
有1900个字节'缺失'.该文件包含短字符串列表.有什么提示为什么它报告不同的文件大小?是否必须对文件中的'\ r'和'\n'字符执行任何操作?另外,我有以下几行:
int bytesLoaded = 0;
Run Code Online (Sandbox Code Playgroud)
如果文件是1GB大,我是否必须使用'long'代替?感谢您的时间!
你的直觉是正确的; 报告大小的差异是由于换行符所致.根据MSDN文档StreamReader.ReadLine:
返回的字符串不包含终止回车符或换行符.
根据创建文件的来源,每个换行符包含一个或两个字符(最常见的是:\r\n在Windows上;仅\n在Linux上).
也就是说,如果您打算将文件作为字节序列读取(不考虑行),则应使用该FileStream.Read方法,这样可以避免ASCII编码的开销(以及返回正确的计数total):
byte[] array = new byte[1024]; // buffer
int total = 0;
using (FileStream fs = File.Open(ListPath, FileMode.Open,
FileAccess.Read, FileShare.ReadWrite))
{
int read;
while ((read = fs.Read(array, 0, array.Length)) > 0)
{
total += read;
// process "array" here, up to index "read"
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:spender提出了关于字符编码的重要观点; 您的代码应仅用于ASCII文本文件.如果您的文件是使用不同的编码编写的 - 今天最流行的是UTF-8 - 那么结果可能不正确.
例如,考虑三字节十六进制序列E2-98-BA.默认StreamReader使用UTF8Encoding,将其解码为单个字符?.但是,此字符不能用ASCII表示; 因此,调用Encoding.ASCII.GetBytes("?")将返回与回退字符的ASCII值相对应的单个字节?,从而导致字符数丢失(以及字节数组的错误处理).
最后,还有可能在文本文件的开头有一个编码前同步码(例如Unicode字节顺序标记),它也会被它剥离ReadLine,导致几个字节的进一步差异.
| 归档时间: |
|
| 查看次数: |
977 次 |
| 最近记录: |