【问题标题】:Character missing from file in certain environments在某些环境中文件中缺少字符
【发布时间】:2013-12-23 16:28:31
【问题描述】:

这对我来说是全新的,我不知道从哪里开始。我有一个 Dictionary 子类,它从本地网络上的旧纯文本文件加载数据以填充自身。

文件有一些标题行,然后是数据(每行由一行破折号分隔),直到每页设定的行数 (59),之后标题重复。

最近有需求增加对最初不需要的数据的支持。此数据没有相同数量的标题列。相反,我决定在每组数据中寻找一个特殊字符。代码如下所示:

/// <summary>
/// Load the work order information from the chart on the network.
/// </summary>
/// <param name="workOrder">Work order to load</param>
/// <param name="model">Model number of the work order to load. Loaded from MES if null.</param>
public WorkOrderInformation(String workOrder, String model)
{
    if (model == null)
        model = MES.getOrder(workOrder).Model;

    String fileLocation = Path.Combine(Path.Combine(WorkOrderLocation, model), workOrder.Insert(4, "-") + ".TXT");

    StreamReader file = new StreamReader(File.Open(fileLocation, FileMode.Open, FileAccess.Read));

    int currentLineNumber = 0;
    while (!file.EndOfStream)
    {
        string line = file.ReadLine();
        Logging.Log.writeLog(log, "Loaded line | " + line);
        currentLineNumber++;
        int lineOnPage =(currentLineNumber % 59);
        // Old way to determine if line contains data
        //if (lineOnPage >= 10 && lineOnPage % 2 == 0)
        if (line.Contains(((char)65533).ToString()))
        {
            Logging.Log.writeLog(log, "Line added to collection");
            string[] sections = line.Split(new char[] { '|' });

            if (sections.Length > 1)
            {
                UnitInfo newUnit = new UnitInfo(sections[0].Trim());
                for (int j = 1; j < sections.Length; j++)
                {
                    newUnit.Add(sections[j].Trim());
                }
                this.Add(newUnit.TestNumber,newUnit);
            }
        }
    }
    file.Close();
}

在我的开发机器 (Windows 7) 和一台部署机器 (Windows 2000) 上,它运行良好。在另一台部署机器 (Windows XP) 上,该字符根本不在行中。如果我检查我的日志,当我记录完整的行和记录“添加到集合的行”的语句时没有写入字符。

我在所有 3 台机器上的同一个文件上运行它。

编辑:

我已更改我的日志记录以存储加载的行的长度而不是行本身,并确认该字符只是从 string 中丢失。在它工作的机器上,日志说这些行的长度为 65 个字符,而在没有的机器上是 64 个。

编辑 2:

我决定重新考虑这个问题。我决定提前拆分字符串并检查第一个值是否是数字,而不是搜索那个特殊字符:

double dummy;
if(double.TryParse(sections[0],out dummy))

这完成了我的工作,但我仍然很好奇为什么会发生这种情况,并且会留下这个问题,希望至少能得到解释。

编辑 3:

似乎比我想象的更多。正如Dan 指出的那样,我正在搜索的值(0xFFFD)实际上是replacement character,它显然不应该是。无法从打印输出中识别字符我在十六进制编辑器中打开文件并发现字符问题应该是 0x00F8 (ø)。

看来 StreamReader 要么加载 0x00F8 作为替换字符,要么根本不加载。现在的问题是为什么?

【问题讨论】:

  • 可能是编码问题。这是一个显示如何将其设置为默认值的问题。 stackoverflow.com/questions/469163/…
  • @TyCobb 哦,这很有道理。我什至不知道编码可能会因环境而异,但如果是这种情况,我宁愿只使用接受编码参数的 StreamReader 构造函数。如何确定 Windows 7 使用的是哪种编码? (这样我就可以使用同一个,因为这似乎有效)
  • 是的,我只是不确定目前用什么更容易测试。我不确定在哪里可以找到适用于 Windows 7 的它。我认为它只是标准的 Encoding.Unicode。您总是可以临时调用Encoding.Default 并设置断点以查看您在该机器上得到了什么。
  • @TyCobb 好吧,当我等待时,我尝试使用 Encoding.Unicode 但这使它将所有字符都解释为亚洲字符。我在我的开发机器上检查了Encoding.Default,它是我从未听说过的System.Text.SBCSCodePageEncoding 类型。然后我继续尝试Encoding.UTF8,它在我的开发机器上完成了工作,但是当我将更新部署到 XP 机器时它仍然无法工作。
  • 仅供参考“SBCS”代表“单字节字符集”。此编码使用 ISO-8859-1。 ISO-8859-1(又名 Latin-1)和 UTF-8 对 ASCII 编码相同;但 ISO-8859-1 是固定长度(单字节)编码,而 UTF-8 是可变长度(可以是单字节或多字节)。 Joel (Spolsky) 比我能更好地解释这一点,请参阅 here

标签: c# file-io c#-2.0


【解决方案1】:

我非常好奇您是如何得出以下代码的:

if (line.Contains(((char)65533).ToString()))

Unicode 65533 或 0xFFFD 是称为replacement character 的特殊字符。此字符的目的是用来代替一些未知或无法表示的字符。

因此,它出现在一行文本中通常表示有一些其他字符由于某种原因无法复制。原因可能是编码、字体等。

期望找到这个符号这一事实似乎是一个根本缺陷。你希望这个角色来自哪里?它会如何在文件中结束?

【讨论】:

  • 这是一个我从未在其他任何地方见过的字符,但我在调试时通过查看相关符号的 char 值获得了该值。这些文件不是在内部生成的,而是由我们的零件供应商之一提供的。它看起来有点像this,但有一条垂直线而不是一条倾斜的线。
  • 那应该是希腊字母 Phi,en.wikipedia.org/wiki/Phi,但 Phi 的 Unicode 绝对不是 0xFFFD。一定是识别字符代码有误,或许可以尝试用十六进制编辑器打开它仔细检查。
  • 有趣。有机会我会检查的。 (考虑到假期,这可能会很热)。
  • 我对这个角色的记忆似乎很模糊,这是我之前找到的那个,而不是 Phi。检查十六进制可以确认,但这仍然不能解决 StreamReader 没有正确加载字符的问题。我已更新我的问题以反映此信息。
  • 有问题的字符(我相信)在斯堪的纳维亚语言中使用。我会说你需要回到零件供应商那里。也许该字符是由于数据输入和/或文件生成过程中的故障/类型造成的——如果您之前没有在供应商数据中看到重音字符,这是一个不无道理的假设。另一方面,如果重音字符实际上是“正确的”,那么您可能不得不处理其他重音字符,甚至可能是非西方字符。
猜你喜欢
  • 2017-06-16
  • 2014-05-12
  • 2019-11-09
  • 1970-01-01
  • 2015-07-23
  • 1970-01-01
  • 2014-01-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多