代码之家  ›  专栏  ›  技术社区  ›  Joe

从C语言的文本文件中读取数字#

  •  19
  • Joe  · 技术社区  · 15 年前

    这应该很简单。我只想从一个文本文件中读取数字和单词,该文件由空格分隔的标记组成。你怎么用C语言做这个?例如,在C++中,下面的代码将用于读取整数、浮点和Word。我不想使用regex或编写任何特殊的解析代码。

    ifstream in("file.txt");
    int int_val;
    float float_val;
    string string_val;
    in >> int_val >> float_val >> string_val;
    in.close();
    

    此外,无论何时读取令牌,都不应读取令牌之外的多个字符。这允许进一步的文件读取取决于所读取的令牌的值。作为一个具体的例子,考虑

    string decider;
    int size;
    string name;
    
    in >> decider;
    if (decider == "name")
        in >> name;
    else if (decider == "size")
        in >> size;
    else if (!decider.empty() && decider[0] == '#')
        read_remainder_of_line(in);
    

    解析二进制PNM文件也是一个很好的例子,可以说明为什么您希望在读取完整令牌后立即停止读取文件。

    6 回复  |  直到 10 年前
        1
  •  24
  •   Jon Skeet    15 年前

    布兰农的回答解释了如何阅读 二元的 数据。如果你想读书 文本 数据,您应该先读取字符串,然后再对它们进行解析——当然,对于这些字符串,有内置的方法。

    例如,要读取包含数据的文件:

    10
    10.5
    hello
    

    您可以使用:

    using (TextReader reader = File.OpenText("test.txt"))
    {
        int x = int.Parse(reader.ReadLine());
        double y = double.Parse(reader.ReadLine());
        string z = reader.ReadLine();
    }
    

    请注意,这没有错误处理。 尤其是,如果文件不存在、前两行数据不正确或少于两行,它将抛出异常。它会留下一个值 null 在里面 z 如果文件只有两行。

    对于一个更强大的解决方案,它可以更优雅地失败,您需要检查 reader.ReadLine() 返回 无效的 (表示文件结束)和使用 int.TryParse double.TryParse 而不是 Parse 方法。

    假设值之间有一个行分隔符。如果您真的想读取这样的字符串:

    10 10.5 hello
    

    那么代码将非常相似:

    using (TextReader reader = File.OpenText("test.txt"))
    {
        string text = reader.ReadLine();
        string[] bits = text.Split(' ');
        int x = int.Parse(bits[0]);
        double y = double.Parse(bits[1]);
        string z = bits[2];
    }
    

    同样,您希望执行适当的错误检测和处理。请注意,如果文件实际上只是由一行组成,则可能需要使用 File.ReadAllText 相反,让它稍微简单一点。还有 File.ReadAllLines 它将整个文件读取到一个字符串行数组中。

    编辑:如果需要拆分 任何 空白,那么你最好用 文件.readalltext 然后使用正则表达式将其拆分。在这一点上,我想知道如何表示一个包含空格的字符串。

    根据我的经验,你通常比这更了解格式——是否会有一个行分隔符,或者在同一行中有多个由空格分隔的值,等等。

    我还要补充一点,混合的二进制/文本格式通常不适合处理。简单而有效的文本处理往往会被读取到缓冲区中,如果有二进制数据的话,这就成了问题。如果您需要二进制文件中的文本部分,那么通常最好包含一个长度前缀,以便仅对该数据段进行解码。

        2
  •  10
  •   Brannon    15 年前
    using (FileStream fs = File.OpenRead("file.txt"))
    {
        BinaryReader reader = new BinaryReader(fs);
    
        int intVal = reader.ReadInt32();
        float floatVal = reader.ReadSingle();
        string stringVal = reader.ReadString();
    }
    
        3
  •  4
  •   John Saunders Tony    10 年前

    我喜欢使用streamreader快速方便地访问文件。比如……

      String file = "data_file.txt";    
      StreamReader dataStream = new StreamReader(file);   
      string datasample;
      while ((datasample = dataStream.ReadLine()) != null)
      {
    
         // datasample has the current line of text - write it to the console.
         Console.Writeline(datasample);
      }
    
        4
  •  3
  •   vgru    15 年前

    不完全是您问题的答案,但如果您不熟悉C:如果您使用自定义文本文件读取某些配置参数,则可能需要检查.NET中的XML序列化主题。

    XML序列化提供了一种写入和读取XML格式文件的简单方法。例如,如果您有这样的配置类:

    public class Configuration
    {
       public int intVal { get; set; }
       public float floatVal { get; set; }
       public string stringVal { get; set; }
    }
    

    您可以使用 XmlSerializer 班级:

    public void Save(Configuration config, string fileName)
    {
       XmlSerializer xml = new XmlSerializer(typeof(Configuration));
       using (StreamWriter sw = new StreamWriter(fileName))
       {
           xml.Serialize(sw, config);
       }
    }
    
    public Configuration Load(string fileName)
    {
       XmlSerializer xml = new XmlSerializer(typeof(Configuration));
       using (StreamReader sr = new StreamReader(fileName)))
       {
           return (Configuration)xml.Deserialize(sr);
       }
    }
    

    Save 上面定义的方法将创建一个包含以下内容的文件:

    <Configuration>
        <intVal>0</intVal>
        <floatVal>0.0</floatVal>
        <stringVal></stringVal>
    </Configuration>
    

    这种方法的好处在于你不需要改变 保存 Load 如果你的方法 Configuration 类更改。

        5
  •  0
  •   jrbalderrama    15 年前

    尝试这样的方法:

    http://stevedonovan.blogspot.com/2005/04/reading-numbers-from-file-in-c.html

    imho也许要读一个C教程,在问之前把整个图片都记在心里是很有用的。

        6
  •  0
  •   Ramashish Baranwal    10 年前

    C似乎没有格式化的流读取器(如C++)(我会很高兴被纠正)。所以jon-skeet将内容读取为字符串并将其解析为所需类型的方法是最好的。