C#: как получить сжатый размер файла?

durka82

Length возвращает реальный размер файла.
А нужно получить его сжатый размер.
НТФС.
Как получить?

Ivan8209

А ещё нам говорят, что в винде есть документация.
---
...Я работаю антинаучным аферистом...

Helga87

Length ты как получаешь сейчас?

Helga87

включая режим телепатии. Сейчас:
FileInfo fi = new FileInfo(fileName);
return fi.Length
Надо:
using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Both)
{
return fs.Length64;
}

durka82

Как бы я его не получал сейчас - все равно твой вариант решения с ним не связан (хотя телепатия у тебя правильная).
Только вот что-то Length64 я в МСДН-е не нашел (правда он у меня не самый новый (который шел с 2005-й студией)
Но в принципе идея понятна: открыть файл в поток и посмотреть размер получившегося потока.
Только вот проблем с быстродействием не будет?
Когда свойства файла/папки в винде смотришь - там эта инфа так же получается?

Helga87

Когда свойства файла/папки в винде смотришь - там эта инфа так же получается?
думаю, нет. Т.к. вполне себе эта цифра может храниться отдельно, записываясь при архивации.
если хочешь, могу показать способ, как узнать размер через обращение к explorer-у, т.е. ровно так, как это делает винда.
про Length64 - наврал, Length и так уже Int64. Где-то в другом месте, значит такое имя всплывало.

durka82

как узнать размер через обращение к explorer-у
Это через cmd? Или через com?
Интересно посмотреть.

Helga87

1. Добавляешь ссылку на библиотеку Shell32.dll, которая лежит в системной директории, кажется
2. Пишешь такой код:

ShellClass sh = new ShellClass;
Folder folder = sh.NameSpace(@"C:\Documents and Settings\dev\Desktop\Zip");
FolderItems items = folder.Items;
for (int i = 0; i < items.Count; i++)
{
FolderItem item = items.Item(i);
Console.WriteLine("{0}\t{1}",item.Name, item.Size);
}

Здесь у меня Zip была сжатая папка и в ней лежали всякие файлы. На экран вывелись настоящие длины файлов, а не размер на диске.

Reves2

если чем порможет, то в winapi есть функция getfilesize,
а как там с с# хз )

durka82

Спасибо, попробую

durka82

Про это я в курсе - в МСДН-е написано - вот только как использовать в C# - разве что через com...

durka82

В общем вроде бы вчера ничего не курил, но такая фигня - точно помню, что вчера выдавались размеры хранимых на диске файлов, а после пробы с FileStream они все показываются как полные размеры
Правда есть идея - что это из-за того, что я файлстримы не закрыл - мб такое?
В общем вечером дома попробую...

durka82

Я уже точно не знаю, что же случилось вчера
Но сейчас все 3 предложенных варианта выдают истинный размер файла.
Значит соответственно мне нужен сжатый размер.
Извините за ошибку.
Переименовал тему.

Helga87

  [DllImport("kernel32.dll", SetLastError = true, EntryPoint = "GetCompressedFileSize")]
static extern uint GetCompressedFileSizeAPI(string lpFileName, out uint lpFileSizeHigh);

uint high;
uint low;
low = GetCompressedFileSizeAPI(@"C:\Documents and Settings\dev\Desktop\Zip\привет.txt", out high);
int error = Marshal.GetLastWin32Error;
if (high == 0 && low == 0xFFFFFFFF && error != 0)
throw new Win32Exception(error);
else
Console.WriteLine( ulong)high << 32) + low);

durka82

Я вот тоже подумывал об использовании GetCompressedFileSize из kernel32.dll, но как референс она к проекту не добавлялась
Попробовал использовать твой пример - первые 2 строки прописал сразу после using.
При компиляции ругается на uint (который static extern uint) - говорит, что expected

Helga87

Когда делаешь DllImport, прописывать reference не нужно. Будет работать прямо тот же код, что у меня написан без дополнительных каких-то действий.

durka82

Спасибо, получилось
Я просто DllImport в неправильное место ставил.
Но чем дальше - тем страшнее
Вообще странно, что в .net нет библиотек для работы с собственными же технологиями (та же нтфс)
Или это они тоже отдали на откуп сторонним разработчикам?

kruzer25

А если не секрет - зачем тебе нужен сжатый размер файла?

durka82

Не секрет.
Чтобы получать информацию о сжимаемости файла.
Потенциально - чтобы сжимать только то, что хорошо жмется, а что плохо жмется - не сжимать (к сожалению винда сама определять не умеет )

kruzer25

А для чего это надо?

durka82

Ускорение работы системы.

kruzer25

Конкретно, что ты хочешь получить? Программу с кнопкой "ускорить работу системы"?
Вообще, есть такое свойство, что для современных процессоров это сжатие вообще незаметно, они это делают очень быстро - и это время компенсируется тем, что приходится меньше читать с винчестера.
Так что, если быстрый процессор - можно смело сжимать вообще всё.
А если почему-то хочется жать только то, что хорошо жмётся - тут уж легче без геморроя типа "сожмём всё, а то, что плохо сжалось, разожмём", гораздо легче просто посмотреть на расширение - если это какие-нибудь mp3/avi/exe/rar/zip/jpg (т.е. уже пожатые данные) - никакого выигрыша ты не получишь. А для reg/inf/txt/htm/doc, в которых сырые данные - выигрыш по объёму уже будет.

durka82

Ну не у всех процессоры самые современные.
И не всегда по расширению можно понять, хорошо ли жмется файл (особенно для игр).
Те же ехе могут сжиматься, а могут и нет.
Хотя в данном случае чтобы понять сжимаемость все равно сначало придется сжать все

Helga87

Вообще странно, что в .net нет библиотек для работы с собственными же технологиями (та же нтфс)
.net пока еще молодая технология, и не все, что хочется в него добавили. Куда больше внимания уделяется тому, чтобы поменьше было глюков. Если не брать вопросы глючности дизайнера в студии (который к рантайму отношения имеет мало то в целом этой цели ms достиг — словосочетание глючный .net достаточно редко встречается.
Одной из попыток сделать примерно то, что ты хочешь, был проект WinFS. Там бы доступ к файловой системе шел через .net, а не через native вызовы (хотя такую возможность они тоже планировали). Проблемой стало то, что они не осилили столько новшеств, сколько запланировали и проект загнулся.

durka82

Ну не такая уж и молодая уже.
Среда действительно подглючивает - у меня периодически падает мсдн (при открытии новых тем но со второго раза открывает...
Про WinFS слышал - действительно жаль, что загнулся.

Helga87

Ну не такая уж и молодая уже.
Она только-только начинает входить в стадию зрелости — когда зарелизится .net 3.5 впервые будет уделено внимание повышению производительности и уменьшению аппетитов по памяти. До этого каждый новый релиз означал серьезные добавления функционала.
Старой и плохой технологией .net станет лет через пять, когда подтянется новое поколение языков и платформ под условия, которые будут к тому моменту: до фига оперативной памяти, многоядер и широкое распространение средств связи. Получится и придется еще больше абстрагироваться от деталей, что и будут позволять делать новые технологии за счет излишков памяти и производительности.

kruzer25

действительно жаль, что загнулся.
Вроде как, в vienna его всё-таки собираются реализовать...

Marinavo_0507

Вообще странно, что в .net нет библиотек для работы с собственными же технологиями (та же нтфс)
.net претендует на роль платформонезависимой технологии, так что имхо правильно, что нет привязки к ntfs
а если завтра будет другая ФС, что должно стать с такими функциями?

durka82

Это еще дождаться надо...

durka82

.net претендует на роль платформонезависимой технологии, так что имхо правильно, что нет привязки к ntfs
Не убедительно.
Вон java - тоже платформонезависимая технология, однако у нее есть моменты, которые реализованы и вообще, и с конкретных частных случаях (драйверы БД например).
А ФС-ов под виндой всего 2, и то одна из них (НТФС) давно позиционируется как основная.
а если завтра будет другая ФС, что должно стать с такими функциями?
Так ООП как раз такие вещи позволяет разруливать.
Единственное объяснение: фичи, которые мало кому нужны, как раз и не реализованы.
Правда мне кажется сомнительным, что такая технология как сжатие данных на дисках мало кому нужна.
Но мб я и ошибаюсь...

Dasar

Правда мне кажется сомнительным, что такая технология как сжатие данных на дисках мало кому нужна.
Но мб я и ошибаюсь...
в таком виде, конечно, мало нужна, потому что требует значительных затрат по управлению...
нужна в прозрачном виде, когда ФС сама прозрачно определяет какие файлы надо сжимать, а какие сжимать не надо.

kruzer25

мне кажется сомнительным, что такая технология как сжатие данных на дисках мало кому нужна
Авторам пользовательского ПО - не нужна. Потому что это нтфс-сжатие как раз позиционируется как абсолютно прозрачное для всех, кроме ОС.
Хочешь непрозрачное сжатие - используй gzip итп.

durka82

Полностью согласен, но есть одно но: со стороны оси как раз технология недоработана
Если бы ось сама умела сжимать/не сжимать в зависимости от сжимаемости/настроек - что-то вроде третьего состояния кроме сжимать или не сжимать - таких вопросов бы не было. Или даже выставлять оптимизацию по скорости или памяти через сжатие.
Но ничего такого нет - налицо недоработанность технологии - поэтому и вопрос возник.
Хочешь непрозрачное сжатие - используй gzip итп.
Все таки в данной ситуации это не альтернатива.
Это актуально только для своих приложений.
Не писать же из-за этого свою ось/файловую систему?..

durka82

С получением размера сжатых файлов все понятно.
Зато теперь неожиданно возник вопрос, как правильно определять размер несжатых файлов.
Я про size on disk.
Ни одна из описанных в теме функций/методов (в том числе и GetCompressedFileSize и GetFileSize из kernel32.dll) не возвращает размер так, как он представлен на главной вкладке свойств файла у свойства size on disk.
Насколько это вообще важно?
Реальный занимаемый размер на диске действительно определяется с точностью до кластера (для несжатых файлов) или эти остатки все таки как-то могут использоваться и этот размер - условность?
В принципе, нужный размер можно вычислять самостоятельно, округляя в большую сторону до размера, кратного размеру кластера, но тут возникает другой вопрос: а как узнать размер кластера у текущего диска? У DriveInfo что-то я такого не нашел. В kernel32.dll тоже.
И еще, когда-то читал, что все мелкие файлы хранятся в MFT, а не как другие файлы.
Вот только не помню критерия мелкости. Но наверное это то, что размер файла меньше размера кластера.
Но вот у меня есть много файлов такого размера, но все они имеют size on disk равный размеру кластера - те получается, что это не так?..
Оставить комментарий
Имя или ник:
Комментарий: