Как определить, содержит ли Строка недопустимые закодированные символы

Места памяти:

File[] roots = context.getExternalFilesDirs(null);
String path = roots[0].getAbsolutePath(); // PhoneMemory
String path = roots[1].getAbsolutePath(); // SCCard (if available)
String path = roots[2].getAbsolutePath(); // USB (if available)

использование

long totalMemory = StatUtils.totalMemory(path);
long freeMemory = StatUtils.freeMemory(path);

final String totalSpace = StatUtils.humanize(totalMemory, true);
final String usableSpace = StatUtils.humanize(freeMemory, true);

Вы можете использовать это

public final class StatUtils {

    public static long totalMemory(String path) {
        StatFs statFs = new StatFs(path);
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {
            //noinspection deprecation
            return (statFs.getBlockCount() * statFs.getBlockSize());
        } else {
            return (statFs.getBlockCountLong() * statFs.getBlockSizeLong());
        }
    }

    public static long freeMemory(String path) {
        StatFs statFs = new StatFs(path);
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {
            //noinspection deprecation
            return (statFs.getAvailableBlocks() * statFs.getBlockSize());
        } else {
            return (statFs.getAvailableBlocksLong() * statFs.getBlockSizeLong());
        }
    }

    public static long usedMemory(String path) {
        long total = totalMemory(path);
        long free = freeMemory(path);
        return total - free;
    }

    public static String humanize(long bytes, boolean si) {
        int unit = si ? 1000 : 1024;
        if (bytes < unit) return bytes + " B";
        int exp = (int) (Math.log(bytes) / Math.log(unit));
        String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp - 1) + (si ? "" : "i");
        return String.format(Locale.ENGLISH, "%.1f %sB", bytes / Math.pow(unit, exp), pre);
    }
}
32
задан Daniel Hiller 23 September 2009 в 05:44
поделиться

8 ответов

Я задал тот же вопрос,

Обработка кодирования символов в URI на Tomcat

Недавно я нашел решение, и оно работает очень хорошо для меня. Возможно, вы захотите попробовать. Вот что вам нужно сделать:

  1. Оставьте кодировку URI как Latin-1. На Tomcat добавьте URIEncoding = "ISO-8859-1" к коннектору в server.xml.
  2. Если вам нужно вручную декодировать URL, также используйте Latin1 в качестве кодировки.
  3. Используйте функцию fixEncoding (), чтобы исправить кодировки.

Например, чтобы получить параметр из строки запроса,

  String name = fixEncoding(request.getParameter("name"));

Ты всегда можешь это сделать. Строка с правильной кодировкой не изменилась.

Код прилагается. Удачи!

 public static String fixEncoding(String latin1) {
  try {
   byte[] bytes = latin1.getBytes("ISO-8859-1");
   if (!validUTF8(bytes))
    return latin1;   
   return new String(bytes, "UTF-8");  
  } catch (UnsupportedEncodingException e) {
   // Impossible, throw unchecked
   throw new IllegalStateException("No Latin1 or UTF-8: " + e.getMessage());
  }

 }

 public static boolean validUTF8(byte[] input) {
  int i = 0;
  // Check for BOM
  if (input.length >= 3 && (input[0] & 0xFF) == 0xEF
    && (input[1] & 0xFF) == 0xBB & (input[2] & 0xFF) == 0xBF) {
   i = 3;
  }

  int end;
  for (int j = input.length; i < j; ++i) {
   int octet = input[i];
   if ((octet & 0x80) == 0) {
    continue; // ASCII
   }

   // Check for UTF-8 leading byte
   if ((octet & 0xE0) == 0xC0) {
    end = i + 1;
   } else if ((octet & 0xF0) == 0xE0) {
    end = i + 2;
   } else if ((octet & 0xF8) == 0xF0) {
    end = i + 3;
   } else {
    // Java only supports BMP so 3 is max
    return false;
   }

   while (i < end) {
    i++;
    octet = input[i];
    if ((octet & 0xC0) != 0x80) {
     // Not a valid trailing byte
     return false;
    }
   }
  }
  return true;
 }

РЕДАКТИРОВАТЬ: Ваш подход не работает по разным причинам. Когда есть ошибки кодирования, вы не можете рассчитывать на то, что получаете от Tomcat. Иногда получается или?. В других случаях вы ничего не получите, getParameter () возвращает null. Скажем, вы можете проверить «?», Что произойдет, если ваша строка запроса содержит действительный знак «?» ?

Кроме того, ни один запрос нельзя отклонять. Это не вина вашего пользователя. Как я уже упоминал в своем первоначальном вопросе, браузер может кодировать URL-адрес либо в UTF-8, либо в Latin-1. Пользователь не имеет контроля. Вам нужно принять и то, и другое. Изменение вашего сервлета на Latin-1 сохранит все символы, даже если они неправильные, чтобы дать нам возможность исправить это или выбросить.

Решение, которое я опубликовал здесь, не идеально, но оно лучшее, что мы нашли на данный момент.

32
ответ дан 27 November 2019 в 20:27
поделиться

URLDecoder will decode to a given encoding. This should flag errors appropriately. However the documentation states:

There are two possible ways in which this decoder could deal with illegal strings. It could either leave illegal characters alone or it could throw an IllegalArgumentException. Which approach the decoder takes is left to the implementation.

So you should probably try it. Note also (from the decode() method documentation):

The World Wide Web Consortium Recommendation states that UTF-8 should be used. Not doing so may introduce incompatibilites

so there's something else to think about!

EDIT: Apache Commons URLDecode claims to throw appropriate exceptions for bad encodings.

3
ответ дан 27 November 2019 в 20:27
поделиться

Вам необходимо настроить кодировку символов с самого начала. Попробуйте отправить правильный заголовок Content-Type , например Content-Type: text / html; charset = utf-8 , чтобы исправить правильную кодировку. Стандартное соответствие ссылается на utf-8 и utf-16 как на правильную кодировку для веб-служб. Изучите заголовки ответов.

Кроме того, на стороне сервера - в случае, когда браузер не обрабатывает должным образом кодировку, отправляемую сервером, - принудительное кодирование путем выделения новой строки. Также вы можете проверить каждый байт в закодированной строке utf-8, выполнив один each_byte & 0x80 , проверив, что результат не равен нулю.


boolean utfEncoded = true;
byte[] strBytes = queryString.getBytes();
for (int i = 0; i < strBytes.length(); i++) {
    if ((strBytes[i] & 0x80) != 0) {
        continue;
    } else {
        /* treat the string as non utf encoded */
        utfEncoded = false;
        break;
    }
}

String realQueryString = utfEncoded ?
    queryString : new String(queryString.getBytes(), "iso-8859-1");

Кроме того, просмотрите эту статью ], Надеюсь, вам это поможет.

1
ответ дан 27 November 2019 в 20:27
поделиться

Вы можете использовать CharsetDecoder, настроенный для выдачи исключения, если обнаружены недопустимые символы:

 CharsetDecoder UTF8Decoder =
      Charset.forName("UTF8").newDecoder().onMalformedInput(CodingErrorAction.REPORT);

См. CodingErrorAction.REPORT

14
ответ дан 27 November 2019 в 20:27
поделиться

Вы можете захотеть включить в свои запросы известный параметр, например "... & encTest = ä €", чтобы безопасно различать разные кодировки.

2
ответ дан 27 November 2019 в 20:27
поделиться

Я работал над аналогичной проблемой «угадай кодировку». Лучшее решение предполагает знание кодировки. За исключением этого, вы можете делать обоснованные предположения, чтобы различать UTF-8 и ISO-8859-1.

Чтобы ответить на общий вопрос о том, как определить, правильно ли закодирована строка в UTF-8, вы можете проверить следующее:

  1. Ни один байт не равен 0x00, 0xC0, 0xC1 или находится в диапазоне 0xF5-0xFF.
  2. Конечным байтам (0x80-0xBF) всегда предшествует начальный байт 0xC2-0xF4 или другой конечный байт.
  3. Начальные байты должен правильно предсказать количество хвостовых байтов (например, за любым байтом в 0xC2-0xDF должен следовать ровно один байт в диапазоне 0x80-0xBF).

Если строка проходит все эти тесты, то она интерпретируется как действительный UTF- 8. Это не гарантирует, что это UTF-8, но это хороший предсказатель.

Допустимый ввод в ISO-8859-1, скорее всего, не будет иметь управляющих символов (0x00-0x1F и 0x80-0x9F), кроме разделителей строк. Похоже, что 0x7F также не определен в ISO-8859-1.

(Я основываю это на страницах Википедии для UTF-8 и ISO-8859-1.)

3
ответ дан 27 November 2019 в 20:27
поделиться

вам может быть интересно следующее регулярное выражение:

http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/185624

I используйте его в Ruby следующим образом:

module Encoding
    UTF8RGX = /\A(
        [\x09\x0A\x0D\x20-\x7E]            # ASCII
      | [\xC2-\xDF][\x80-\xBF]             # non-overlong 2-byte
      |  \xE0[\xA0-\xBF][\x80-\xBF]        # excluding overlongs
      | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}  # straight 3-byte
      |  \xED[\x80-\x9F][\x80-\xBF]        # excluding surrogates
      |  \xF0[\x90-\xBF][\x80-\xBF]{2}     # planes 1-3
      | [\xF1-\xF3][\x80-\xBF]{3}          # planes 4-15
      |  \xF4[\x80-\x8F][\x80-\xBF]{2}     # plane 16
    )*\z/x unless defined? UTF8RGX

    def self.utf8_file?(fileName)
      count = 0
      File.open("#{fileName}").each do |l|
        count += 1
        unless utf8_string?(l)
          puts count.to_s + ": " + l
        end
      end
      return true
    end

    def self.utf8_string?(a_string)
      UTF8RGX === a_string
    end

end
1
ответ дан 27 November 2019 в 20:27
поделиться

Попробуйте использовать UTF-8 по умолчанию, как всегда, где бы вы ни коснулись. (База данных, память и пользовательский интерфейс)

Использование одной и той же кодировки может уменьшить множество проблем и фактически может повысить производительность вашего веб-сервера. На кодирование / декодирование тратится так много вычислительной мощности и памяти.

0
ответ дан 27 November 2019 в 20:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: