【问题标题】:How to remove a char from a string, based on its codepage index?如何根据其代码页索引从字符串中删除字符?
【发布时间】:2019-12-02 06:42:29
【问题描述】:

我正在用 C# 编写一个 .NET 软件,它应该将数据从一个数据库传输到另一个数据库。 每个索引大于 127codepage 1252 的字符都会在目标数据库中引起问题,因此我想在将这些字符从值(字符串)中删除之前,再将它们写入目标数据库。 p>

我一直在搜索和尝试很多,但直到现在我只找到了针对 ASCII 或 UTF 索引执行此操作的解决方案。我需要代码页 1252 索引的解决方案。

编辑:这是迄今为止我最接近的方法:

protected string GetSqlValue(string input, bool isStringValue = true)
{
    if (string.IsNullOrWhiteSpace(input)) return "''";
    else
    {
        //TODO: remove all characters with an index greater than 127 in codepage 1252.
        Encoding targetEncoding = Encoding.GetEncoding(1252);
        byte[] tmp = targetEncoding.GetBytes(input);
        for (int i=0;i<tmp.Length;i++)
        {
            if (tmp[i] > 127) tmp = tmp.Where((source, index) => index != i).ToArray();
        }
        input = targetEncoding.GetString(tmp);

        if (isStringValue) return "'" + input + "'";
        else return input;
    }
}

【问题讨论】:

  • 欢迎来到 SO。我建议先阅读the tour,然后阅读How to AskMinimal, Complete, and Verifiable example,了解SO 的工作原理以及如何有效地提出问题。最重要的是,向我们展示您目前拥有的代码。
  • 到目前为止你尝试过什么?你能给我们看一些代码吗?
  • 到目前为止,我还没有此主题的工作代码。实际上我有一个方法protected string GetSqlValue(string input),如果参数为空、空或仅包含空格,则返回“NULL”。如果不是这种情况,这些方法只返回到目前为止的参数。我在这里的要求是我想添加到这个方法中的东西,到目前为止我什至还没有接近解决方案。
  • 好的,我已经添加了我认为迄今为止最接近的方法。

标签: c# string char codepages


【解决方案1】:

我不得不承认我对问题的根源有误。 原来,一些数据还包含几个撇号。那些破坏了目标数据库的 DDL 和 DML 语句。 我还必须防止德语变音符号也被删除。

所以我的方法的最终版本现在看起来像这样:

/// <summary>
/// Gets the SQL value as German characters of codepage 1252.
/// </summary>
/// <param name="input">The string to convert for the target database.</param>
/// <param name="isStringValue">if set to <c>true</c> return encapsulated in single quotation marks.</param>
/// <returns>"''", or the value itself.</returns>
protected string GetSqlValue(string input, bool isStringValue = true)
{
    if (string.IsNullOrWhiteSpace(input)) return "''";
    else
    {
        Encoding targetEncoding = Encoding.GetEncoding(1252);

        // Remove all characters that are not part of codepage 1252.
        input = targetEncoding.GetString(targetEncoding.GetBytes(input));

        // Remove unsupported special characters.
        byte[] tmp = targetEncoding.GetBytes(input);
        for (int i = 0; i < tmp.Length; i++)
        {
            // Don't delete German umlauts.
            if (tmp[i] == 0xc4 /* Ä */ || tmp[i] == 0xe4 /* ä */ || tmp[i] == 0xd6 /* Ö */ || tmp[i] == 0xf6 /* ö */ || tmp[i] == 0xdc /* Ü */ || tmp[i] == 0xfc /* ü */) continue;

            // Delete non German characters and all kind of apostrophes.
            if (tmp[i] >= 0x80 || tmp[i] < 0x20 || tmp[i] == 0x27 || tmp[i] == 0x60) tmp = tmp.Where((source, index) => index != i).ToArray();
        }
        input = targetEncoding.GetString(tmp);

        if (isStringValue) return "'" + input + "'";
        else return input;
    }
}

非常感谢您的帮助。

P.S.:我知道这个问题不是应该的。一旦我更多地了解这里应该如何做,我会做得更好。

【讨论】:

    【解决方案2】:

    在我向您展示您的问题的解决方案之前,我建议您先查看一下您的编码(在 DB 和代码中)并解决这些问题,而不是删除字符。

    您的解决方案忽略了单个字符可以由多个字节表示。这里是一个 unicode 示例:

    Console.WriteLine("a: " + string.Join("-", Encoding.Unicode.GetBytes("a").Select(s => s.ToString("X2"))));
    Console.WriteLine("€: " + string.Join("-", Encoding.Unicode.GetBytes("€").Select(s => s.ToString("X2"))));
    

    您必须检查字符串中的每个字符并仅选择符合您要求的字符。

    static void Main(string[] args)
    {
        string str = "abc€def!\"§$%&/()=?`";
    
        var enc = Encoding.GetEncoding(1252);
    
        Console.WriteLine("All:     " + str);
        // Select all chars which have a total value below 128
        IEnumerable<char> chars = str.Where(s => ConvertLittleEndian(enc.GetBytes(s + "")) < 128);
    
        // reassamble string
        Console.WriteLine("Reduced: " + String.Concat(chars));
    }
    
    static ulong ConvertLittleEndian(byte[] array)
    {
        int pos = 0;
        ulong result = 0;
        foreach (byte by in array)
        {
            result |= ((ulong)by) << pos;
            pos += 8;
        }
        return result;
    }
    

    静态方法ConvertLittleEndian() 是这个问题的第一个答案的副本: Convert byte array to int

    【讨论】:

    • 我认为单个字符的多个字节的问题在这里无关紧要,因为代码页1252只有256个值,所以它应该始终是每个字符一个字节。如果我的假设有误,请纠正我。
    • 对代码页 1252 更正,但如果他只使用此代码页,则数据库不会有问题。我认为他的编码有更大的问题。无论如何,我提供的解决方案对他有用。
    • 也许我应该解释问题的根源。正如我之前所说,我的软件的目标是将数据从一个数据库传输到另一个数据库。这是我工作的公司的 ERP 交换的一部分。问题是源数据库是为国际使用而设置的,而目标数据库仅设置为德语(LanguageID 1031 和代码页 1252)。由于目标数据库不支持在代码页 1252 中设置索引大于 127 的目标数据库字符,因为它们不是德语字母表的一部分。
    猜你喜欢
    • 2019-12-22
    • 2012-11-16
    • 1970-01-01
    • 1970-01-01
    • 2023-01-07
    • 2023-01-10
    • 2021-09-12
    • 1970-01-01
    • 2018-02-27
    相关资源
    最近更新 更多