c # и Encoding.ASCII.GetString - PullRequest
2 голосов
/ 31 мая 2009
byte[] header = new byte[]{255, 216}; 

string ascii =  Encoding.ASCII.GetString(header);

Я ожидаю, что ASCII будет равен FFD8 (маркер JPEG SOI)

Вместо этого я получаю "????"

Ответы [ 5 ]

11 голосов
/ 31 мая 2009

В этом случае лучше сравнивать байтовые массивы, чем преобразовывать их в строку.

Если вам необходимо преобразовать в строку, я предлагаю использовать кодировку Latin-1, также известную как ISO-8859-1 или Code Code 28591, так как эта кодировка отобразит все байты с шестнадцатеричными значениями в диапазоне 0-255 в Unicode символ с тем же шестнадцатеричным значением - удобно для этого сценария. Любое из следующего получит эту кодировку:

Encoding.GetEncoding(28591)
Encoding.GetEncoding("Latin1")
Encoding.GetEncoding("ISO-8859-1")
8 голосов
/ 31 мая 2009

Да, это потому, что ASCII является только 7-разрядным - он не определяет значения выше 127. Кодировки обычно декодируют неизвестные двоичные значения в '?' (хотя это можно изменить с помощью DecoderFallback ).

Если вы собираетесь упомянуть "расширенный ASCII", я подозреваю, что вы действительно хотите Encoding.Default, который является "кодовой страницей по умолчанию для операционной системы" ... кодовая страница 1252 в большинстве западных систем Я верю.

Каких персонажей вы ожидали?

РЕДАКТИРОВАТЬ: В соответствии с принятым ответом (я подозреваю, что вопрос был отредактирован после того, как я добавил свой ответ; я не помню, чтобы когда-либо видел что-то про JPEG изначально), вы не должны преобразовывать двоичные данные в текст, если это не подлинно кодированные текстовые данные. Данные JPEG - это двоичные данные - поэтому вы должны сверять фактические байты с ожидаемыми байтами.

Каждый раз, когда вы преобразуете произвольные двоичные данные (например, изображения, музыку или видео) в текст, используя «простую» кодировку текста (например, ASCII, UTF-8 и т. Д.), Вы рискуете потерять данные. Если у вас есть для преобразования его в текст, используйте Base64, что приятно и безопасно. Однако, если вы просто хотите сравнить его с ожидаемыми двоичными данными, лучше вообще не преобразовывать его в текст.

РЕДАКТИРОВАТЬ: Хорошо, вот класс, чтобы помочь метод обнаружения изображений для данного байтового массива. Я не сделал это HTTP-специфичным; Я не совсем уверен, следует ли вам действительно получить InputStream, прочитать его немного, а затем снова получить поток. Я решил проблему, придерживаясь байтовых массивов:)

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;

public sealed class SignatureDetector
{
    public static readonly SignatureDetector Png =
        new SignatureDetector(0x89, 0x50, 0x4e, 0x47);

    public static readonly SignatureDetector Bmp =
        new SignatureDetector(0x42, 0x4d);

    public static readonly SignatureDetector Gif =
        new SignatureDetector(0x47, 0x49, 0x46);

    public static readonly SignatureDetector Jpeg =
        new SignatureDetector(0xff, 0xd8);

    public static readonly IEnumerable<SignatureDetector> Images =
        new ReadOnlyCollection<SignatureDetector>(new[]{Png, Bmp, Gif, Jpeg});

    private readonly byte[] bytes;

    public SignatureDetector(params byte[] bytes)
    {
        if (bytes == null)
        {
            throw new ArgumentNullException("bytes");
        }
        this.bytes = (byte[]) bytes.Clone();
    }

    public bool Matches(byte[] data)
    {
        if (data == null)
        {
            throw new ArgumentNullException("data");
        }
        if (data.Length < bytes.Length)
        {
            return false;
        }
        for (int i=0; i < bytes.Length; i++)
        {
            if (data[i] != bytes[i])
            {
                return false;
            }
        }
        return true;
    }    

    // Convenience method
    public static bool IsImage(byte[] data)
    {
        return Images.Any(detector => detector.Matches(data));
    }        
}
1 голос
/ 01 июня 2009

Я однажды написал собственный кодер / декодер, который кодировал байты 0-255 в символы юникода 0-255 и обратно.

Это было действительно полезно только для использования строковых функций на чем-то, что на самом деле не является строкой.

1 голос
/ 31 мая 2009

Если вы тогда написали:

Console.WriteLine(ascii)

И ожидал, что «FFD8» распечатает, GetString работает не так. Для этого вам понадобится:

 string ascii = String.Format("{0:X02}{1:X02}", header[0], header[1]);   
0 голосов
/ 31 мая 2009

Вы уверены, что "????" это результат?

Что является результатом:

(int)ascii[0]
(int)ascii[1]

С другой стороны, чистый ASCII только 0-127 ...

...