Тот код нормализует разрывы строки, которые могут или не могут быть тем, что Вы действительно хотите сделать.
Вот альтернатива, которая не делает этого, и которая является (IMO) более простой понять, чем код NIO (хотя это все еще использует java.nio.charset.Charset
):
public static String readFile(String file, String csName)
throws IOException {
Charset cs = Charset.forName(csName);
return readFile(file, cs);
}
public static String readFile(String file, Charset cs)
throws IOException {
// No real need to close the BufferedReader/InputStreamReader
// as they're only wrapping the stream
FileInputStream stream = new FileInputStream(file);
try {
Reader reader = new BufferedReader(new InputStreamReader(stream, cs));
StringBuilder builder = new StringBuilder();
char[] buffer = new char[8192];
int read;
while ((read = reader.read(buffer, 0, buffer.length)) > 0) {
builder.append(buffer, 0, read);
}
return builder.toString();
} finally {
// Potential issue here: if this throws an IOException,
// it will mask any others. Normally I'd use a utility
// method which would log exceptions and swallow them
stream.close();
}
}
Изучите другие разработанные библиотеки. Многие люди хотели сделать это до вас. : D
Попробуйте bigint C ++
Не изобретайте велосипед - я уверен, что другие люди уже решили эту проблему, хотя я не могу придумать какие-либо решения. GMP , безусловно, может решить вашу проблему, хотя это излишне для целых чисел фиксированного размера, а также немного громоздко в использовании (это библиотека C, а не C ++).
Возможно, вам лучше использовать целочисленный класс бесконечной точности, а не последовательность увеличивающегося размера. Некоторые языки (например, Common Lisp и IIRC Python) имеют их изначально. Я не совсем уверен, что доступно для C ++; в последний раз я не видел версии Boost.
В Visual Studio C ++ существует тип FLOAT128, который используется для представления 128-битных целых чисел. Он реализован как
#if defined(_M_IA64) && !defined(MIDL_PASS)
__declspec(align(16))
#endif
typedef struct _FLOAT128 {
__int64 LowPart;
__int64 HighPart;
} FLOAT128;
, поэтому я не уверен, какие математические операции для него реализованы
РЕДАКТИРОВАТЬ: когда я впервые написал это boost :: multiprecision :: uint128_t
еще не было. Сохраняем этот ответ по историческим причинам.
Я создал класс uint128 раньше, вы можете проверить его по адресу: http://www.codef00.com/code/uint128.h .
] Он зависит от ускорения для автоматического предоставления всех вариантов математических операторов, поэтому он должен поддерживать все, что делает собственный тип unsigned int
.
Есть некоторые незначительные расширения для встроенных типов, такие как инициализируя его такой строкой:
uint128_t x("12345678901234567890");
Существует вспомогательный макрос, который работает аналогично макросам в C99, и вы можете использовать его следующим образом:
uint128_t x = U128_C(12345678901234567890);
Это в некотором роде особый случай, тем более что вы не указали, какие платформы вы ищете, но с GCC вы можете использовать так называемый режим (TI) для получить (синтезировать) 128-битные операции, например:
typedef unsigned int uint128_t __attribute__((mode(TI)));
uint64_t x = 0xABCDEF01234568;
uint64_t y = ~x;
uint128_t result = ((uint128_t) x * y);
printf("%016llX * %016llX -> ", x, y);
uint64_t r1 = (result >> 64);
uint64_t r2 = result;
printf("%016llX %016llX\n", r1, r2);
Но это работает только на 64-битных процессорах.
Так или иначе, для решения этой проблемы вы смотрите на арифметику с множественной точностью. mode (TI) заставит компилятор генерировать операции за вас, в противном случае они должны быть написаны явно.
Вы можете использовать общий пакет bigint; известные мне на C ++ включают пакеты теории чисел LiDIA и NTL , а также пакеты bigint, используемые для криптографического кода в Crypto ++ и Botan ]). Плюс конечно есть GnuMP , которая является канонической библиотекой C MPI (и у нее также есть оболочка C ++, хотя в прошлый раз, когда я смотрел на нее, она казалась плохо документированной). Все они разработаны, чтобы быть быстрыми, но также, вероятно, настроены для больших (1000+ бит) чисел, поэтому при 128 битах вы можете иметь дело с большими накладными расходами. (С другой стороны, вы не говорите, имеет это значение или нет). И все они (в отличие от пакета bigint-cpp, который является GPL, либо BSD, либо LGPL) - не уверен, имеет ли это значение - но это может иметь большое значение.
Вы также можете написать собственный тип типа uint128_t; обычно такой класс будет реализовывать те же алгоритмы, что и обычный класс MPI, только жестко запрограммированный, чтобы иметь только 2 или 4 элемента. Если вам интересно, как реализовать такие алгоритмы, хорошая ссылка - Глава 14 Справочника по прикладной криптографии
. Конечно, делать это вручную проще, если вам на самом деле не нужны все арифметические операции (деление и по модулю, в частности, довольно сложны). Например, если вам просто нужно отслеживать счетчик, который гипотетически может переполнять 64 бита, вы можете просто представить его как пару длинных 64-битных длин и выполнить перенос вручную:
unsigned long long ctrs[2] = { 0 };
void increment() {
++ctrs[0];
if(!ctrs[0]) // overflow
++ctrs[1];
}
Что, конечно, будет гораздо проще иметь дело, чем с обычным пакетом MPI или пользовательским классом uint128_t.