需要使用 StreamReader.ReadLine() 获取行终止符

2023-11-21

我编写了一个 C# 程序来读取 Excel .xls/.xlsx 文件并输出为 CSV 和 Unicode 文本。我编写了一个单独的程序来删除空白记录。这是通过读取每一行来完成的StreamReader.ReadLine(),然后逐个字符地遍历字符串,如果该行包含所有逗号(对于 CSV)或所有制表符(对于 Unicode 文本),则不写入要输出的行。

当 Excel 文件的单元格内包含嵌入的换行符 (\x0A) 时,会出现此问题。我将 XLS 更改为 CSV 转换器来查找这些新行(因为它逐个单元地进行)并将它们写为 \x0A,而普通行只需使用 StreamWriter.WriteLine()。

问题出现在删除空白记录的单独程序中。当我读到StreamReader.ReadLine(),根据定义,它仅返回带有行的字符串,而不返回终止符。由于嵌入的换行符显示为两个单独的行,因此当我将它们写入最终文件时,我无法分辨哪一个是完整记录,哪一个是嵌入式换行符。

我什至不确定我是否可以读取 \x0A,因为输入上的所有内容都注册为“\n”。我可以一个字符一个字符地进行操作,但这破坏了我删除空行的逻辑。


我建议您更改架构,使其更像编译器中的解析器。

您想要创建一个返回标记序列的词法分析器,然后创建一个读取标记序列并对其进行处理的解析器。

在你的情况下,令牌将是:

  1. 列数据
  2. Comma
  3. 行结束

您可以将 '\n' ('\x0a') 本身视为嵌入的新行,因此将其作为列数据标记的一部分。 '\r\n' 将构成行结束标记。

这样做的优点是:

  1. 仅对数据进行 1 次传递
  2. 最多只存储 1 行数据
  3. 重用尽可能多的内存(用于字符串生成器和列表)
  4. 如果您的需求发生变化,很容易改变

以下是词法分析器的示例:

免责声明:我什至还没有编译过这段代码,更不用说测试了,所以您需要清理它并确保它有效。

enum TokenType
{
    ColumnData,
    Comma,
    LineTerminator
}

class Token
{
    public TokenType Type { get; private set;}
    public string Data { get; private set;}

    public Token(TokenType type)
    {
        Type = type;
    }

    public Token(TokenType type, string data)
    {
        Type = type;
        Data = data;
    }
}

private  IEnumerable<Token> GetTokens(TextReader s)
{
   var builder = new StringBuilder();

   while (s.Peek() >= 0)
   {
       var c = (char)s.Read();
       switch (c)
       {
           case ',':
           {
               if (builder.Length > 0)
               {
                   yield return new Token(TokenType.ColumnData, ExtractText(builder));
               }
               yield return new Token(TokenType.Comma);
               break;
           }
           case '\r':
           {
                var next = s.Peek();
                if (next == '\n')
                {
                    s.Read();
                }

                if (builder.Length > 0)
                {
                    yield return new Token(TokenType.ColumnData, ExtractText(builder));
                }
                yield return new Token(TokenType.LineTerminator);
                break;
           }
           default:
               builder.Append(c);
               break;
       }

   }

   s.Read();

   if (builder.Length > 0)
   {
       yield return new Token(TokenType.ColumnData, ExtractText(builder));
   }
}

private string ExtractText(StringBuilder b)
{
    var ret = b.ToString();
    b.Remove(0, b.Length);
    return ret;
}

您的“解析器”代码将如下所示:

public void ConvertXLS(TextReader s)
{
    var columnData = new List<string>();
    bool lastWasColumnData = false;
    bool seenAnyData = false;

    foreach (var token in GetTokens(s))
    {
        switch (token.Type)
        {
            case TokenType.ColumnData:
            {
                 seenAnyData = true;
                 if (lastWasColumnData)
                 {
                     //TODO: do some error reporting
                 }
                 else
                 {
                     lastWasColumnData = true;
                     columnData.Add(token.Data);
                 }
                 break;
            }
            case TokenType.Comma:
            {
                if (!lastWasColumnData)
                {
                    columnData.Add(null);
                }
                lastWasColumnData = false;
                break;
            }
            case TokenType.LineTerminator:
            {
                if (seenAnyData)
                {
                    OutputLine(lastWasColumnData);
                }
                seenAnyData = false;
                lastWasColumnData = false;
                columnData.Clear();
            }
        }
    }

    if (seenAnyData)
    {
        OutputLine(columnData);
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

需要使用 StreamReader.ReadLine() 获取行终止符 的相关文章

  • UTF8/UTF16 和 Base64 在编码方面有什么区别

    In c 我们可以使用下面的类来进行编码 System Text Encoding UTF8 System Text Encoding UTF16 System Text Encoding ASCII 为什么没有System Text En
  • 在 LINQ 查询中返回不带时间的日期

    我正在编写一个查询 我想计算按日期联系我们的呼叫中心的次数 看起来很简单 但由于联系日期字段是日期时间字段 我得到了时间 因此当我按联系日期 时间 分组时 每个联系日期实例的计数为 1 所以 我想只按日期分组 而不按时间分组 下面是我用来查
  • 自动从 C# 代码进行调试过程并读取寄存器值

    我正在寻找一种方法来读取某个地址的 edx 注册表 就像这个问题中所问的那样 读取eax寄存器 https stackoverflow com questions 16490906 read eax register 虽然我的解决方案需要用
  • 模板类的不明确多重继承

    我有一个真实的情况 可以总结为以下示例 template lt typename ListenerType gt struct Notifier void add listener ListenerType struct TimeListe
  • FFMPEG Seeking 带来音频伪影

    我正在使用 ffmpeg 实现音频解码器 在读取音频甚至搜索已经可以工作时 我无法找到一种在搜索后清除缓冲区的方法 因此当应用程序在搜索后立即开始读取音频时 我没有任何工件 avcodec flush buffers似乎对内部缓冲区没有任何
  • 将字符串从非托管代码传递到托管

    我在将字符串从非托管代码传递到托管代码时遇到问题 在我的非托管类中 非托管类 cpp 我有一个来自托管代码的函数指针 TESTCALLBACK FUNCTION testCbFunc TESTCALLBACK FUNCTION 接受一个字符
  • 写入和读取文本文件 - C# Windows 通用平台应用程序 Windows 10

    有用 但在显示任何内容之前 您必须在文本框中输入内容 我想那是因为我使用了 TextChanged 事件处理程序 如果我希望它在没有用户交互的情况下显示文本文件的内容 我应该使用哪个事件处理程序 因此 我想在按下按钮时将一些数据写入 C W
  • 使用安全函数在 C 中将字符串添加到字符串

    我想将文件名复制到字符串并附加 cpt 但我无法使用安全函数 strcat s 来做到这一点 错误 字符串不是空终止的 我确实设置了 0 如何使用安全函数修复此问题 size strlen locatie size nieuw char m
  • 编译的表达式树会泄漏吗?

    根据我的理解 JIT 代码在程序运行时永远不会从内存中释放 这是否意味着重复调用 Compile 表达式树上会泄漏内存吗 这意味着仅在静态构造函数中编译表达式树或以其他方式缓存它们 这可能不那么简单 正确的 他们可能是GCed Lambda
  • Windows 10 中 Qt 桌面应用程序的缩放不当

    我正在为 Windows 10 编写一个简单的 Qt Widgets Gui 应用程序 我使用的是 Qt 5 6 0 beta 版本 我遇到的问题是它根本无法缩放到我的 Surfacebook 的屏幕上 这有点难以判断 因为 SO 缩放了图
  • 像“1$”这样的位置参数如何与 printf() 一起使用?

    By man I find printf d width num and printf 2 1 d width num 是等价的 但在我看来 第二种风格应该与以下相同 printf d num width 然而通过测试似乎man是对的 为什
  • C 中的位移位

    如果与有符号整数对应的位模式右移 则 1 vacant bit will be filled by the sign bit 2 vacant bit will be filled by 0 3 The outcome is impleme
  • 什么是 C 语言的高效工作流程? - Makefile + bash脚本

    我正在开发我的第一个项目 该项目将跨越多个 C 文件 对于我的前几个练习程序 我只是在中编写了我的代码main c并使用编译gcc main c o main 当我学习时 这对我有用 现在 我正在独自开展一个更大的项目 我想继续自己进行编译
  • 在 URL 中发送之前对特殊字符进行百分比编码

    我需要传递特殊字符 如 等 Facebook Twitter 和此类社交网站的 URL 为此 我将这些字符替换为 URL 转义码 return valToEncode Replace 21 Replace 23 Replace 24 Rep
  • 将日期参数传递给对 MVC 操作的 ajax 调用的安全方法

    我有一个 MVC 操作 它的参数之一是DateTime如果我通过 17 07 2012 它会抛出一个异常 指出参数为空但不能有空值 但如果我通过01 07 2012它被解析为Jan 07 2012 我将日期传递给 ajax 调用DD MM
  • char指针或char变量的默认值是什么[重复]

    这个问题在这里已经有答案了 下面是我尝试打印 char 变量和指针的默认值 值的代码 但无法在控制台上看到它 它是否有默认值或只是无法读取 ASCII 范围 include
  • 在Linux中使用C/C++获取机器序列号和CPU ID

    在Linux系统中如何获取机器序列号和CPU ID 示例代码受到高度赞赏 Here http lxr linux no linux v2 6 39 arch x86 include asm processor h L173Linux 内核似
  • 如何使用 ReactiveList 以便在添加新项目时更新 UI

    我正在创建一个带有列表的 Xamarin Forms 应用程序 itemSource 是一个reactiveList 但是 向列表添加新项目不会更新 UI 这样做的正确方法是什么 列表定义 listView new ListView var
  • 如何在 C# 中播放在线资源中的 .mp3 文件?

    我的问题与此非常相似question https stackoverflow com questions 7556672 mp3 play from stream on c sharp 我有音乐网址 网址如http site com aud
  • 为什么 strtok 会导致分段错误?

    为什么下面的代码给出了Seg 最后一行有问题吗 char m ReadName printf nRead String s n m Writes OK char token token strtok m 如前所述 读取字符串打印没有问题 但

随机推荐

  • PhoneGap Eclipse 问题 - eglCodecCommon glUtilsParamSize:未知参数错误

    我刚刚开始使用phonegap 并尝试在eclipse 中设置第一个基本的最小项目 我按照以下位置的phonegap文档进行操作http docs phonegap com en edge guide platforms android i
  • MySQL InnoDB 不同数据库之间的外键

    我想知道在 InnoDB 中是否可以MySQL有一个table with 外键引用不同的另一个表database 如果是这样 如何做到这一点 我没有看到任何限制https dev mysql com doc refman 8 0 en cr
  • Django-Celery 正在生产中吗?

    所以我一直在试图弄清楚如何制定计划任务 我找到了 Celery 并且能够制定简单的计划任务 为此 我需要打开命令行并运行celery A proj beat为了任务的发生 这在开发环境中工作得很好 但是当将其投入生产时 这将是一个问题 那么
  • 从 64 位整数秒计数创建 boost::posix_time::ptime 对象

    我有一个 32 位 Linux 系统 在其中我必须记录时间戳为距 1901 01 01 00 00 00 的 UINT32 秒偏移量的数据 计算时间戳对我来说没问题 因为我可以使用 64 位ticks 计数器和ticks per secon
  • 使用 matplotlib 添加自定义刻度

    我想在matplotlib数字 目前 我使用以下命令添加刻度 例如 axis set yticks 0 5 0 6 0 7 0 8 0 9 1 0 我希望能够做到 axis set yticks 1 0 some custom text 所
  • Grails 2.x createCriteria 'or' 不适用于嵌套关联

    似乎在 Grails 2 x 中 如果您有一个域类关联 并且您尝试使用以下命令运行 createCriteriaor在该关系 另一个查询上 or将忽略其他查询并仅使用嵌套关联的结果 我意识到这可能有点令人困惑 所以这里是一个例子 class
  • SQLite更新触发器更改表中的所有行

    问题 最简单的更新触发器将新值写入所有表行 而不仅仅是正在更新的行 这是表格 names id INTEGER PRIMARY KEY name TEXT len INTEGER 现在我想创建触发器来用 name 的长度更新 len 这个
  • Selenium Webdriver:元素不可见异常

    这是我的代码 用于单击一个简单的登录按钮Website import java util concurrent TimeUnit import org openqa selenium By import org openqa seleniu
  • UIAccessibility 元素的自定义 UITableViewCell 问题

    无论我尝试什么 我都无法阻止我的自定义 UITableViewCell 发挥作用就像应该的那样根据 UIAccessiblity 的默认规则 我不希望这个单元格充当可访问性容器 本身 所以遵循这个guide我应该能够使我的所有子视图都可访问
  • 宽度和高度会随方向变化吗?

    所以我的游戏从垂直方向开始 然后最终进入水平方向 我知道屏幕的宽度是屏幕的宽度 与垂直方向时的高度相同 当它切换到水平方向时 高度会变成宽度 宽度会变成高度吗 或者它们保持不变 是的 屏幕宽度和高度会根据设备方向而变化 您可以使用以下命令获
  • 如何在 C# 中将 UTC 时间转换为任何其他时区的时间

    我正在 C net 中工作 Net fx 是 2 0 不支持不同时区之间的转换 我已经编写了一个基于 UTC 的调度程序 但它在伦敦的 DTS 周期中给出了 1 小时的错误 我需要一些解决方案 以便我可以通过正确的 DST 调整来获得相对于
  • 将 int 转换为 4 字节 char 数组 (C)

    嘿 我希望将用户输入的 int 转换为 4 个字节 并将其分配给字符数组 如何才能做到这一点 Example 将用户输入 175 转换为 00000000 00000000 00000000 10101111 到目前为止所有答案都有问题 转
  • 查看单个文档中单个字段的原始 Solr 标记

    我正在调试我的 Solr 架构 我想查看标记特定字段的结果 举一个简化的例子 如果我有
  • sudo E选项不起作用? [关闭]

    Closed 这个问题不符合堆栈溢出指南 目前不接受答案 在我看来 如果我写一个shell脚本 HOME path to script myscript and export PATH PATH HOME path to script th
  • 在单活动架构中设置片段的横向方向

    如何实现只锁定一个屏幕方向Fragment 在单活动架构中 只有一个Activity对于整个应用程序 有没有比在每个中指定请求的方向更好的解决方案Fragment 我试图避免放置activity requestedOrientation A
  • 在 scrapy 中运行多个蜘蛛

    例如 在 scrapy 中 如果我有两个包含不同 HTML 的 URL 现在我想分别编写两个单独的蜘蛛 并希望同时运行这两个蜘蛛 在 scrapy 中可以同时运行多个蜘蛛 在scrapy中编写多个蜘蛛后 我们如何安排它们每6小时运行一次 可
  • 依赖于子目录同级的介子目标

    这是我的项目结构 include src abc include src def include src ghi include src vendor bar include src foo 16 directories 我想将我的构建移植
  • 如何从其他应用程序向 Microsoft 团队发布消息

    我正在尝试在我的桌面应用程序中创建一个自定义方法 使用 C 以向 Microsoft 团队发布消息 但我还是不知道用什么样的工具或者服务来完成 有可能实现吗 如果是 怎么办 我在 Visual Studio 中找到了一个有关 MS Team
  • 在 matplotlib 中重用 patch 对象而不移动它们的位置

    我想自动生成一系列被剪裁成补丁的图 如果我尝试重复使用补丁对象 它会在画布上移动位置 该脚本 基于 Yann 对之前问题的回答 演示了正在发生的情况 import pylab as plt import scipy as sp import
  • 需要使用 StreamReader.ReadLine() 获取行终止符

    我编写了一个 C 程序来读取 Excel xls xlsx 文件并输出为 CSV 和 Unicode 文本 我编写了一个单独的程序来删除空白记录 这是通过读取每一行来完成的StreamReader ReadLine 然后逐个字符地遍历字符串