Как я могу вычислить полный размер буфера для GetModuleFileName?

Правильное решение использует экземпляр EntityManager.

entityManager.getReference(YourClass.class, id);

Поскольку этот метод принимает только один идентификатор, вам нужно написать собственный запрос SQL (используя HQL или собственный SQL), чтобы получить только идентификаторы необходимых объектов.

Имея List<T> ids, вы можете чем

final List<YourClass> proxyValues = 
         ids.stream()
            .map(id -> entityManager.getReference(YourClass.class, id))
            .collect(Collectors.toList());

Говоря о производительности, это прекрасно, так как доступ к базе данных будет осуществляться один раз, извлекая небольшой объем данных. [1110 ]

12
задан Roman R. 8 April 2015 в 06:21
поделиться

2 ответа

Реализуйте разумную стратегию увеличения буфера, например, начните с MAX_PATH, затем увеличьте каждый последующий размер в 1,5 раза (или в 2 раза за меньшее количество итераций), чем предыдущий. Итерируйте, пока функция не выполнится успешно.

9
ответ дан 2 December 2019 в 18:22
поделиться

Обычный рецепт - вызвать его, установив размер на ноль, и он гарантированно потерпит неудачу и предоставит размер, необходимый для выделения достаточного буфера , Выделите буфер (не забывайте место для нулевого завершения) и вызовите его во второй раз.

Во многих случаях MAX_PATH достаточно, потому что многие файловые системы ограничивают общую длину файла. путь Тем не мение, возможно создать допустимые и полезные имена файлов, которые превышают MAX_PATH , поэтому, вероятно, это хороший совет для запроса требуемого буфера.

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

Редактировать: Фрэнсис указывает в комментарии, что обычный рецепт не работает для GetModuleFileName () . К сожалению, Фрэнсис абсолютно прав в этом вопросе, и мое единственное оправдание в том, что я не посмотрел его, чтобы проверить, прежде чем предлагать «обычное» решение.

Я не знаю, о чем думал автор этого API за исключением того, что возможно, что когда он был представлен, MAX_PATH действительно был максимально возможным путем, что облегчало правильный рецепт. Просто выполните все манипуляции с именами файлов в буфере длиной не менее MAX_PATH символов.

О, да, не забывайте, что имена путей с 1995 года или около того допускают символы Unicode. Поскольку Unicode занимает больше места, перед любым именем пути может стоять \\? \ , чтобы явно запросить, чтобы ограничение MAX_PATH на длину его байта было удалено для этого имени. Это усложняет вопрос.

MSDN имеет это, чтобы сказать о длине пути в статье под названием Имена файлов, пути и пространства имен :

Максимальная длина пути

В API Windows (с некоторыми любому имени пути может предшествовать \\? \ , чтобы явно запросить, чтобы ограничение MAX_PATH на его длину в байтах было снято для этого имени. Это усложняет вопрос.

MSDN имеет это, чтобы сказать о длине пути в статье под названием Имена файлов, пути и пространства имен :

Максимальная длина пути

В API Windows (с некоторыми любому имени пути может предшествовать \\? \ , чтобы явно запросить, чтобы ограничение MAX_PATH на его длину в байтах было снято для этого имени. Это усложняет вопрос.

MSDN имеет это, чтобы сказать о длине пути в статье под названием Имена файлов, пути и пространства имен :

Максимальная длина пути

В API Windows (с некоторыми исключения обсуждаются в следующем пункты), максимальная длина для путь MAX_PATH , который определяется как 260 символов. Локальный путь структурирован в следующем порядке: буква диска, двоеточие, обратный слеш, компоненты, разделенные обратной косой чертой, и завершающий нулевой символ. Для Например, максимальный путь на диске D is " D: \ <путь 256 символов строка> "где" "представляет невидимый завершающий ноль символ для текущей системы кодовая. (Используются символы < > здесь для наглядности и не может быть часть допустимой строки пути.)

Примечание Функции ввода-вывода файла в Windows API преобразует " / " в " \ " как часть преобразования имени в стиль NT имя, кроме случаев использования " \\? \ " префикс, как описано в следующем разделы.

Windows API имеет много функций которые также имеют версии Unicode для разрешить путь расширенной длины для максимальная общая длина пути 32 767 персонажи. Этот тип пути состоит из компонентов, разделенных обратная косая черта, каждая до значения вернулся в Параметр lpMaximumComponentLength из функция GetVolumeInformation . к укажите путь расширенной длины, используйте префикс " \\? \ ". Например, " \\? \ D: \ <очень длинный путь> ". (The символы < > используются здесь для визуальная четкость и не может быть частью допустимая строка пути.)

Примечание. Максимальный путь составляет 32 767 символы приблизительны, потому что Префикс « \\? \ » может быть расширен до более длинная строка системой при запуске время, и это расширение относится к общая длина.

Также можно использовать префикс " \\? \ " с путями, построенными в соответствии с универсальное соглашение об именах (UNC). Чтобы указать такой путь с помощью UNC, используйте префикс « \\? \ UNC \ ». Например, « \\? \ UNC \ server \ share », где «сервер» это имя машины и "поделиться" это имя общей папки. Эти префиксы не используются как часть сам путь. Они указывают, что путь должен быть передан система с минимальной модификацией, а это значит, что вы не можете использовать косая черта для представления пути разделители, или период для представления текущий каталог. Вас также нельзя использовать префикс « \\? \ » с относительный путь, следовательно, относительный пути ограничены MAX_PATH символы, как указано ранее для пути, не использующие префикс « \\? \ ».

При использовании API для создания каталог, указанный путь не может быть настолько длинным, что вы не можете добавить 8.3 имя файла (то есть имя каталога не может превышать MAX_PATH минус 12).

Оболочка и файловая система имеют разные требования. Это возможно создать путь с помощью Windows API что пользовательский интерфейс оболочки может не может справиться.

Таким образом, простым ответом будет выделение буфера размером MAX_PATH , получение имени и проверка на наличие ошибок. Если это подходит, вы сделали. В противном случае, если он начинается с « \\? \ », получите буфер размером 64 КБ или около того (фраза «максимальный путь из 32 767 символов является приблизительным» выше - это немного неприятно, поэтому я ухожу некоторые детали для дальнейшего изучения) и попробуйте снова.

Переполнение MAX_PATH , но не начинающееся с « \\? \ », похоже, «не может случиться». Опять же, что делать, это деталь, с которой вам придется иметь дело.

Также может быть некоторая путаница в отношении ограничения длины пути для имени сети, которое начинается " \\ Server \ Share \ », не говоря уже об именах из пространства имен объектов ядра, которые начинаются с " \\. \ ". В приведенной выше статье ничего не сказано, и я не уверен, сможет ли этот API вернуть такой путь.

10
ответ дан 2 December 2019 в 18:22
поделиться
Другие вопросы по тегам:

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