如何从 C stdio.h getline() 替换/忽略无效的 Unicode/UTF8 字符?

2023-12-07

在Python上,有这个选项errors='ignore'为了openPython函数:

open( '/filepath.txt', 'r', encoding='UTF-8', errors='ignore' )

这样,读取包含无效 UTF8 字符的文件时,它们将被替换为空,即它们被忽略。例如,包含字符的文件Føö»BÃ¥r将被读作FøöBår.

如果一行作为Føö»BÃ¥r是用getline() from stdio.h,它将被读作Føö�Bår:

FILE* cfilestream = fopen( "/filepath.txt", "r" );
int linebuffersize = 131072;
char* readline = (char*) malloc( linebuffersize );

while( true )
{
    if( getline( &readline, &linebuffersize, cfilestream ) != -1 ) {
        std::cerr << "readline=" readline << std::endl;
    }
    else {
        break;
    }
}

我怎样才能使stdio.h getline()将其读作FøöBår代替Føö�Bår,即忽略无效的 UTF8 字符?

我能想到的一个压倒性的解决方案是迭代每行上的所有字符读取并构建一个新的readline没有任何这些字符。例如:

FILE* cfilestream = fopen( "/filepath.txt", "r" );
int linebuffersize = 131072;
char* readline = (char*) malloc( linebuffersize );
char* fixedreadline = (char*) malloc( linebuffersize );

int index;
int charsread;
int invalidcharsoffset;

while( true )
{
    if( ( charsread = getline( &readline, &linebuffersize, cfilestream ) ) != -1 )
    {
        invalidcharsoffset = 0;
        for( index = 0; index < charsread; ++index )
        {
            if( readline[index] != '�' ) {
                fixedreadline[index-invalidcharsoffset] = readline[index];
            } 
            else {
                ++invalidcharsoffset;
            }
        }
        std::cerr << "fixedreadline=" << fixedreadline << std::endl;
    }
    else {
        break;
    }
}

相关问题:

  1. 修复无效的 UTF8 字符
  2. 替换非 UTF8 字符
  3. python 替换unicode字符
  4. Python unicode:如何用空格替换无法使用utf8解码的字符?

你混淆了你所看到的和真实发生的事情。这getline函数不做任何字符替换。 [注1]

您看到替换字符 (U+FFFD) 是因为您的控制台在要求呈现无效的 UTF-8 代码时输出该字符。大多数控制台在 UTF-8 模式下都会这样做;也就是说,当前的语言环境是 UTF-8。

另外,说文件包含“字符Føö»BÃ¥r“充其量是不精确的。文件并不真正包含字符。它包含可以解释为字符的字节序列 - 例如,通过控制台或其他用户演示软件将它们呈现为字形 - 根据某种编码。不同不同的编码会产生不同的结果;在这种特殊情况下,您有一个由软件使用 Windows-1252 编码(或者大致相当于 ISO 8859-15)创建的文件,并且您使用 UTF-8 在控制台上渲染它。

这意味着 getline 读取的数据包含无效的 UTF-8 序列,但它(可能)不包含替换字符代码。根据您提供的字符串,它包含十六进制字符\xbb,这是海鸠(»)在 Windows 代码页 1252 中。

查找读取的字符串中所有无效的 UTF-8 序列getline(或任何其他读取文件的 C 库函数)需要扫描字符串,但不需要扫描特定的代码序列。相反,您需要一次解码一个 UTF-8 序列,查找无效的序列。这不是一个简单的任务,但是mbtowc函数可以提供帮助(如果您启用了 UTF-8 语言环境)。正如您将在链接的联机帮助页中看到的,mbtowc返回有效“多字节序列”(UTF-8 语言环境中的 UTF-8)中包含的字节数,或 -1 表示无效或不完整的序列。在扫描中,您应该以有效序列传递字节,或者删除/忽略开始无效序列的单个字节,然后继续扫描直到到达字符串末尾。

下面是一些经过简单测试的示例代码(C 语言):

#include <stdlib.h>
#include <string.h>

/* Removes in place any invalid UTF-8 sequences from at most 'len' characters of the
 * string pointed to by 's'. (If a NUL byte is encountered, conversion stops.)
 * If the length of the converted string is less than 'len', a NUL byte is
 * inserted.
 * Returns the length of the possibly modified string (with a maximum of 'len'),
 * not including the NUL terminator (if any).
 * Requires that a UTF-8 locale be active; since there is no way to test for
 * this condition, no attempt is made to do so. If the current locale is not UTF-8,
 * behaviour is undefined.
 */
size_t remove_bad_utf8(char* s, size_t len) {
  char* in = s;
  /* Skip over the initial correct sequence. Avoid relying on mbtowc returning
   * zero if n is 0, since Posix is not clear whether mbtowc returns 0 or -1.
   */
  int seqlen;
  while (len && (seqlen = mbtowc(NULL, in, len)) > 0) { len -= seqlen; in += seqlen; }
  char* out = in;

  if (len && seqlen < 0) {
    ++in;
    --len;
    /* If we find an invalid sequence, we need to start shifting correct sequences.  */
    for (; len; in += seqlen, len -= seqlen) {
      seqlen = mbtowc(NULL, in, len);
      if (seqlen > 0) {
        /* Shift the valid sequence (if one was found) */
        memmove(out, in, seqlen);
        out += seqlen;
      }
      else if (seqlen < 0) seqlen = 1;
      else /* (seqlen == 0) */ break;
    }
    *out++ = 0;
  }
  return out - s;
}

Notes

  1. 除了底层 I/O 库可能的行尾转换之外,这将用单个替换 CR-LF\n在像 Windows 这样的系统上,两个字符 CR-LF 序列用作行结束指示。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何从 C stdio.h getline() 替换/忽略无效的 Unicode/UTF8 字符? 的相关文章

  • 结构化绑定中缺少类型信息

    我刚刚了解了 C 中的结构化绑定 但有一件事我不喜欢 auto x y some func is that auto正在隐藏类型x and y 我得抬头看看some func的声明来了解类型x and y 或者 我可以写 T1 x T2 y
  • 在模板类中声明模板友元类时出现编译器错误

    我一直在尝试实现我自己的链表类以用于教学目的 我在迭代器声明中指定了 List 类作为友元 但它似乎无法编译 这些是我使用过的 3 个类的接口 Node h define null Node
  • 在一个数据访问层中处理多个连接字符串

    我有一个有趣的困境 我目前有一个数据访问层 它必须与多个域一起使用 并且每个域都有多个数据库存储库 具体取决于所调用的存储过程 目前 我只需使用 SWITCH 语句来确定应用程序正在运行的计算机 并从 Web config 返回适当的连接字
  • -webkit-box-shadow 与 QtWebKit 模糊?

    当时有什么方法可以实现 webkit box shadow 的工作模糊吗 看完这篇评论错误报告 https bugs webkit org show bug cgi id 23291 我认识到这仍然是一个问题 尽管错误报告被标记为RESOL
  • 用于 FTP 的文件系统观察器

    我怎样才能实现FileSystemWatcherFTP 位置 在 C 中 这个想法是 每当 FTP 位置添加任何内容时 我都希望将其复制到我的本地计算机 任何想法都会有所帮助 这是我之前问题的后续使用 NET 进行选择性 FTP 下载 ht
  • 需要帮助优化算法 - 两百万以下所有素数的总和

    我正在尝试做一个欧拉计划 http projecteuler net问题 我正在寻找 2 000 000 以下所有素数的总和 这就是我所拥有的 int main int argc char argv unsigned long int su
  • WPF 数据绑定到复合类模式?

    我是第一次尝试 WPF 并且正在努力解决如何将控件绑定到使用其他对象的组合构建的类 例如 如果我有一个由两个单独的类组成的类 Comp 为了清楚起见 请注意省略的各种元素 class One int first int second cla
  • 人脸 API DetectAsync 错误

    我想创建一个简单的程序来使用 Microsoft Azure Face API 和 Visual Studio 2015 检测人脸 遵循 https social technet microsoft com wiki contents ar
  • WcfSvcHost 的跨域异常

    对于另一个跨域问题 我深表歉意 我一整天都在与这个问题作斗争 现在已经到了沸腾的地步 我有一个 Silverlight 应用程序项目 SLApp1 一个用于托管 Silverlight SLApp1 Web 的 Web 项目和 WCF 项目
  • x:将 ViewModel 方法绑定到 DataTemplate 内的事件

    我基本上问同样的问题这个人 https stackoverflow com questions 10752448 binding to viewmodels property from a template 但在较新的背景下x Bind V
  • C 编程:带有数组的函数

    我正在尝试编写一个函数 该函数查找行为 4 列为 4 的二维数组中的最大值 其中二维数组填充有用户输入 我知道我的主要错误是函数中的数组 但我不确定它是什么 如果有人能够找到我出错的地方而不是编写新代码 我将不胜感激 除非我刚去南方 我的尝
  • 如何在当前 Visual Studio 主机内的 Visual Studio 扩展中调试使用 Roslyn 编译的代码?

    我有一个 Visual Studio 扩展 它使用 Roslyn 获取当前打开的解决方案中的项目 编译它并从中运行方法 程序员可以修改该项目 我已从当前 VisualStudioWorkspace 成功编译了 Visual Studio 扩
  • 如何实例化 ODataQueryOptions

    我有一个工作 简化 ODataController用下面的方法 public class MyTypeController ODataController HttpGet EnableQuery ODataRoute myTypes pub
  • C 函数 time() 如何处理秒的小数部分?

    The time 函数将返回自 1970 年以来的秒数 我想知道它如何对返回的秒数进行舍入 例如 对于100 4s 它会返回100还是101 有明确的定义吗 ISO C标准没有说太多 它只说time 回报 该实现对当前日历时间的最佳近似 结
  • 相当于Linux中的导入库

    在 Windows C 中 当您想要链接 DLL 时 您必须提供导入库 但是在 GNU 构建系统中 当您想要链接 so 文件 相当于 dll 时 您就不需要链接 为什么是这样 是否有等效的 Windows 导入库 注意 我不会谈论在 Win
  • 对于某些 PDF 文件,LoadIFilter() 返回 -2147467259

    我正在尝试使用 Adob e IFilter 搜索 PDF 文件 我的代码是用 C 编写的 我使用 p invoke 来获取 IFilter 的实例 DllImport query dll SetLastError true CharSet
  • 当文件流没有新数据时如何防止fgets阻塞

    我有一个popen 执行的函数tail f sometextfile 只要文件流中有数据显然我就可以通过fgets 现在 如果没有新数据来自尾部 fgets 挂起 我试过ferror and feof 无济于事 我怎样才能确定fgets 当
  • 在OpenGL中,我可以在坐标(5, 5)处精确地绘制一个像素吗?

    我所说的 5 5 正是指第五行第五列 我发现使用屏幕坐标来绘制东西非常困难 OpenGL 中的所有坐标都是相对的 通常范围从 1 0 到 1 0 为什么阻止程序员使用屏幕坐标 窗口坐标如此严重 最简单的方法可能是通过以下方式设置投影以匹配渲
  • MySQL Connector C/C API - 使用特殊字符进行查询

    我是一个 C 程序 我有一个接受域名参数的函数 void db domains query char name 使用 mysql query 我测试数据库中是否存在域名 如果不是这种情况 我插入新域名 char query 400 spri
  • 类型或命名空间“MyNamespace”不存在等

    我有通常的类型或命名空间名称不存在错误 除了我引用了程序集 using 语句没有显示为不正确 并且我引用的类是公共的 事实上 我在不同的解决方案中引用并使用相同的程序集来执行相同的操作 并且效果很好 顺便说一句 这是VS2010 有人有什么

随机推荐

  • 为什么循环顺序会影响二维数组迭代时的性能?

    下面是两个几乎相同的程序 除了我切换了i and j周围的变数 它们运行的 时间不同 有人可以解释为什么会发生这种情况吗 版本1 include
  • python/tkinter 绘图程序撤消函数

    我尝试在我的绘画程序中添加一个撤消功能 该功能从画布中删除对象 创建的每个对象都附加到堆栈中 我尝试了它 它可以工作 但屏幕不会仅在第一个撤消时更新 因此如果我绘制 3 条线然后我撤消什么也不会发生 当我一次又一次撤消时 第二行和第三行将被
  • 在 ImageView 上的 OnTouch 中返回 false,但事件仍然被消耗

    我在用ImageView onTouch 我返回 falseACTION MOVE但仍然是onTouch 事件被消耗 imageView setOnTouchListener new View OnTouchListener Overrid
  • 交换字符串中的大小写[重复]

    这个问题在这里已经有答案了 我正在尝试解决Hackerrank 中的这项挑战 它要求将所有小写字母转换为大写字母 反之亦然 我尝试使用以下代码 def swap case s length len s i 0 while length if
  • 从 R 闪亮的 selectInput 中过滤

    我试图让用户上传 csv 文件 然后获取该 csv 文件的一列 因子 并创建用户输入 以确定将为数据框选择该字段中的哪个唯一名称 因此 如果我有以下示例 data frame COURSE VALUE 1 A 7 2 C 2 3 C 2 4
  • 在 SSIS 中动态更改服务器名称

    我的 SSIS 包在开发周期 开发 QA 暂存和生产 期间会经历多个环境 因此我想使用 SSIS 中的配置来设置连接管理器中的服务器名称 这样我就不会不需要手动完成此操作 我读过有关使用 xml 配置文件 SQL 配置表和环境变量的内容 然
  • 谷歌地图:未捕获的类型错误:类型错误

    在几个页面上 我开始收到上述错误 但仅在 Chrome 中 这是一些简单的代码来演示该错误
  • 使用 boost::dynamic_bitset 作为键值对序列化 boost::bimap

    我有兴趣序列化boost bimap含有boost dynamic bitset这样我就可以保存它并在需要时加载回来 我已经尝试这样做 但遇到了很多错误 我随身携带的代码如下 Example program include
  • python 中的布尔值是可变的吗?

    我在 python 中有以下代码 def update request id success 0 try product Mattress objects get id id success 1 except Mattress DoesNo
  • C# 内存地址和变量

    在C 中 有没有办法 获取存储在a中的内存地址 引用类型变量 获取a的内存地址 多变的 EDIT int i int pi i 如何打印 pi 的十六进制值 对于 2 运算符的工作方式与 C 中相同 如果变量不在堆栈上 您可能需要使用fix
  • 从“SecKeychainFindGenericPassword”给出的“SecKeychainItemRef”中提取“用户名”?

    从这个问题 我知道你可以使用SecKeychainFindGenericPassword without用户名值 它仍然会返回给定服务的钥匙串项 但是我如何获取用户名呢 仅使用服务名称获取存储在钥匙串中的用户名 或者 您应该在哪里存储用户名
  • 是否可以将网页内容读入字符串中,以便我可以解析数据?

    我希望能够让我的 iPhone 将 URL 或者实际上是 url 指向的文件 加载到字符串中 我希望能够执行此操作的原因是这样我就可以解析字符串以查找标签并从中提取一些值 这些文件主要是网页 例如 html 或 asp 等 有人能给我一些提
  • 导出并发布 Typescript 中的所有类型和接口

    我正在尝试发布一个打字稿库 我不清楚如何公开所有类型和接口 这是我的设置 mylib src types mytypes ts index ts package json tsconfig json index ts import MyIn
  • Firefox - 删除未修饰复选框的边框

    我有一个复选框appearance none 这在 Chrome 中有效 但在 Firefox 中它留下了一个我无法删除的插入边框 我努力了border none已经 我这里有一个小提琴 http jsfiddle net jcJJ5 不幸
  • 根据 HTML 文本匹配产品价格

    我正在尝试在字符串上使用简单的正则表达式来获取定价信息 但是我的preg match all根本就是没有找到它应该找到的东西 我正在寻找例如 or 或者有时货币符号可能被编码为 HTML 实体 例如对于英镑 pound or 163 使用有
  • Django:在模型 save() 方法中返回序列化器 ValidationError

    我使用 django rest framework 在 Django 框架内创建 Rest API 并且可以返回任何validationError除了序列化器方法之外 但是 我想知道是否有可能返回错误save Django的方法model被
  • 将函数更改为 PDO

    这是我的api中使用的语句 这是第二个 result下面整个函数中的变量 如何将其更改为使用 PDO result query SELECT p IdPhoto p device token title p IdUser FROM phot
  • 如何在nodejs中向mysql查询回调传递参数

    我试图找出将自定义数据传递到查询调用以在回调中可用的正确方法 我在nodejs 中使用MySQL 库 所有最新版本 我调用了 connection query sql function err result 我找不到一种方法来 1 将自定义
  • 在父元素内将对象序列化为 XML

    我有一个 WPF C 程序 有时我需要将对象序列化为 XML 在其他地方 我一直在使用这个 TextWriter writer new StreamWriter xmlFilePath XmlSerializer xmlSerializer
  • 如何从 C stdio.h getline() 替换/忽略无效的 Unicode/UTF8 字符?

    在Python上 有这个选项errors ignore 为了openPython函数 open filepath txt r encoding UTF 8 errors ignore 这样 读取包含无效 UTF8 字符的文件时 它们将被替换