Что нового

[Данные, строки] Побайтовое обнуление в файле начиная с адреса 0xFFFFFF

Black_Hole

Знающий
Сообщения
126
Репутация
11
Допустим есть файл 5Гб, надо обнулить 256 байт начиная с адреса 0xFFFFFF

Ps. ткните носом куда копать, если не сложно простенький пример.
 
Автор
B

Black_Hole

Знающий
Сообщения
126
Репутация
11
Kaster
это порядковый номер символа (в шестнадцатеричной системе) в файле, допустим есть пространство 00...09 байт (10 байт или 10 ячеек как кому удобно) надо допустим ячейкам 07 и 08 присвоить значения 0х00.

В принципе все просто, только файл не 10 байт а 5Гб, и надо функция, метод, переменная или что то другое чтобы считывалась только незначительная часть из файла для замены и сохранения, 5гб одним куском обрабатывать не логично и не разумно, можно разбить на три части (начало, рабочая часть, окончание) выполнить нужные действия и потом склеить, но надо как то порезать на куски, да и хотелось что то по проще =)
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4,020
Репутация
626
попробуй так
Код:
$h = FileOpen('filepath', 16+2)
FileSetPos($h, Dec(0xFFFFFF), $FILE_BEGIN)
$sZeros = Chr(0)
For $i = 1 to 255
    $sZeros &= Chr(0)
Next
FileWrite($h, $sZeros)
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
Black_Hole,
Попробуйте так, у меня работает.
Код:
#include <FileConstants.au3>

Global $sFile = 'big.txt', $bText, $bReplace, $hFile, $hFileNew, $iPos = 0x00010030, $iSize, _
		$iMod, $iEnd, $iPart = 1024 * 1024 * 10, $iTime, $iTmp = 0, $iLen

;Без проверок на ошибки
;#cs
;долго пишет новый файл 100 Mb
$hFile = FileOpen(@ScriptDir & '\' & $sFile, 16 + 2)
For $j = 1 To 100
	$bText = ''
	For $i = 1 To 1024 * 1024
		$bText &= Chr($iTmp)
		$iTmp += 1
		Switch $iTmp
			Case 256
				$iTmp = 0
		EndSwitch
	Next
	FileWrite($hFile, Binary($bText))
Next
FileClose($hFile)
$bText = ''
;#ce

For $i = 192 To 255
	$bReplace &= Chr($i)
Next
ConsoleWrite('Строка замены String: ' & $bReplace & @LF)
$bReplace = Binary($bReplace)
ConsoleWrite('Строка замены Binary: ' & $bReplace & @LF)
$iLen = BinaryLen($bReplace)

;читаем до изменения
$hFile = FileOpen(@ScriptDir & '\' & $sFile, 16)
FileSetPos($hFile, $iPos, $FILE_BEGIN)
$bText = FileRead($hFile, $iLen)
FileClose($hFile)
ConsoleWrite('до Binary: ' & $iPos & @TAB & $bText & @LF)
ConsoleWrite('до String: ' & $iPos & @TAB & BinaryToString($bText) & @LF)

$iTime = TimerInit()
$iSize = FileGetSize(@ScriptDir & '\' & $sFile)
$hFile = FileOpen(@ScriptDir & '\' & $sFile, 16)

$hFileNew = FileOpen(@ScriptDir & '\New_' & $sFile, 16 + 2)
If $iPos > $iPart Then
	$iTmp = Int($iPos / $iPart)
	$iMod = Mod($iPos, $iPart)
	For $i = 1 To $iTmp
		$bText = FileRead($hFile, $iPart)
		FileWrite($hFileNew, $bText)
	Next
	$bText = FileRead($hFile, $iMod)
	FileWrite($hFileNew, $bText & $bReplace)
	FileRead($hFile, $iLen)
	While 1
		$bText = FileRead($hFile, $iPart)
		If @error Then ExitLoop
		FileWrite($hFileNew, $bText)
	WEnd
Else
	$bText = FileRead($hFile, $iPos)
	$bText &= $bReplace
	FileWrite($hFileNew, $bText)
	FileRead($hFile, $iLen)
	While 1
		$bText = FileRead($hFile, $iPart)
		If @error Then ExitLoop
		FileWrite($hFileNew, $bText)
	WEnd
EndIf
FileClose($hFile)
FileClose($hFileNew)
ConsoleWrite('Time: ' & TimerDiff($iTime) & @LF)
$bText = ''
FileMove(@ScriptDir & '\New_' & $sFile, @ScriptDir & '\' & $sFile, 1)
;читаем после изменения
$hFile = FileOpen(@ScriptDir & '\' & $sFile, 16)
FileSetPos($hFile, $iPos, $FILE_BEGIN)
$bText = FileRead($hFile, $iLen)
FileClose($hFile)
ConsoleWrite('после Binary: ' & $iPos & @TAB & $bText & @LF)
ConsoleWrite('после String: ' & $iPos & @TAB & BinaryToString($bText) & @LF)



Добавлено:
Сообщение автоматически объединено:

Kaster [?]
Не работает. :(
 
Автор
B

Black_Hole

Знающий
Сообщения
126
Репутация
11
Kaster
Ваш код с незначительными ошибками, за функцию FileSetPos спасибо, это именно то что было нужно.

Если кому понадобится, ниже исправленный вариант с комментариями.
Код:
#include <Constants.au3>

dim $string
$file = "c:\5Gb.bin"	;Файл для патча
$point = 0x10			;Точка входа в файл (17 символ)
$size = 0xff			;Количество изменяемых байт (255)
$Null = chr(0x00)		;Заменяющий символ (обнуление)
$openfile = FileOpen($file, 16+1)
FileSetPos($openfile, $point, $FILE_BEGIN)
For $i = 0 to $size
    $string &= $Null
Next
FileWrite($openfile, $string)
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4,020
Репутация
626
Black_Hole [?]
Ваш код с незначительными ошибками
c какими? я вот смотрю на твой код и свой и единственная разница это
Код:
FileSetPos($h, Dec(0xFFFFFF), $FILE_BEGIN); у меня
;--------------
$point = 0x10
FileSetPos($openfile, $point, $FILE_BEGIN); у тебя

однако ты сам сказал
[?]
надо обнулить 256 байт начиная с адреса 0xFFFFFF


Добавлено:
Сообщение автоматически объединено:

хотя, я не подключил библиотеку.


Добавлено:
Сообщение автоматически объединено:

и для Dec нужна строка.
ок, согласен :smile:
 
Автор
B

Black_Hole

Знающий
Сообщения
126
Репутация
11
Kaster, начнем по порядку:

Ваш вариант кода (не рабочий):
Код:
$h = FileOpen('filepath', 16+2)
FileSetPos($h, Dec(0xFFFFFF), $FILE_BEGIN)
$sZeros = Chr(0)
For $i = 1 to 255
    $sZeros &= Chr(0)
Next
FileWrite($h, $sZeros)


1) без либы било ошибку
Код:
#include <FileConstants.au3>


2) затирало файл до точки входа
Код:
FileOpen('filepath', 16+2)


3) первый байт присваивался еще до входа в цикл, если переменная одна и имеет одно значение, меняется она должна в одном месте, а не по нескольку раз в разных местах в коде.
Код:
$sZeros = Chr(0)
For $i = 1 to 255
    $sZeros &= Chr(0)


4) если полностью не перелопатить и не исправить ошибки КПД ноль, все было переписано отталкиваясь от функции FileSetPos с исправлением ошибок.

Мой вариант (рабочий):
Код:
#include <Constants.au3>

dim $string
$file = "c:\5Gb.bin"    ;Файл для патча
$point = 0x10           ;Точка входа в файл (17 символ)
$size = 0xff            ;Количество изменяемых байт (255)
$Null = chr(0x00)       ;Заменяющий символ (обнуление)
$openfile = FileOpen($file, 16+1)
FileSetPos($openfile, $point, $FILE_BEGIN)
For $i = 0 to $size
    $string &= $Null
Next
FileWrite($openfile, $string)
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4,020
Репутация
626
Black_Hole [?]
3) первый байт присваивался еще до входа в цикл, если переменная одна и имеет одно значение, меняется она должна в одном месте, а не по нескольку раз в разных местах в коде.
это ты сам придумал? :smile:
по остальным - согласен.
 
Автор
B

Black_Hole

Знающий
Сообщения
126
Репутация
11
Kaster
не будем спорить, согласитесь что мой код отвечает на поставленную задачу идеально, благодаря вашей наводке на функцию он и был написан, в этом есть ваша заслуга ;)
 

AZJIO

Меценат
Меценат
Сообщения
2,879
Репутация
1,194
Black_Hole
Для этого
Код:
For $i = 0 to $size
    $string &= $Null
Next

есть функция _StringRepeat

Но Melba23 на офсайте предложил использовать StringFormat, пример:
Код:
$n = 1024 * 100
$0 = Chr(0)
$0 = Chr(28)

$timer1 = TimerInit()
$sText = StringReplace(StringFormat("%0" & $n & "d", "0"), "0", $0, 0, 2)
$timer1 = Round(TimerDiff($timer1), 2)
MsgBox(0, 'Время : ' & $timer1 & ' мсек', $sText)

$timer2 = TimerInit()
$sText = ''
For $i = 1 To $n
	$sText &= $0
Next
$timer2 = Round(TimerDiff($timer2), 2)
MsgBox(0, 'Время : ' & $timer2 & ' мсек', $sText)


Скорость операции увеличивается в 10 раз.
Только я не тестировал на максимально допустимую длину выходной строки.

Вот ещё пример с записью непосредственно в файл. Думаю не будет ограничение связанные с памятью, так как пишется сразу в файл.
Код:
#include <Constants.au3>

$file = @ScriptDir&'\Копия тест.au3'    ;Файл для патча
$point = 0x10           ;Точка входа в файл (17 символ)
$size = 0xff            ;Количество изменяемых байт (255)
$Null = chr(0x00)       ;Заменяющий символ (обнуление)
$openfile = FileOpen($file, 16+1)
FileSetPos($openfile, $point, $FILE_BEGIN)
For $i = 0 to $size
	FileWrite($openfile, $Null)
Next
FileClose($openfile)
 
Автор
B

Black_Hole

Знающий
Сообщения
126
Репутация
11
AZJIO

Код:
dim $string

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

Код:
For $i = 0 to $size
    $string &= $Null
Next

самое главное на что стоит обратить внимание это что только в цикле к пустой переменной добавляются $Null и только потом они сохраняются (некогда не поверю что сложение 255 байт в строку и запись в файл одной строкой будет медленнее, чем запись 255 символов по отдельности в файл), в вашем псевдо-исправленном примере нет сдвига байта, как это будет происходить, если сдвигать точку входа тогда надо еще цикл для ее.

Код:
For $i = 0 to $size
    FileWrite($openfile, $Null)
Next

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

Код:
FileWrite($openfile, $Null &= chr(0x00))

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

Код:
$string &= $Null
в моем варианте $Null может быть байтом, старкой и даже файлом и при единичном цикле запишется как надо, если понадобится в файл А записать файл Б, переменной $Null надо только присвоить одну строчку FileRead(FileOpen(ФайлБ), 16+1)) и все.

Бесплатный чудо патчер на все случаи жизни!
Код:
#include <Constants.au3>

dim $string
$file = "c:\5Gb.bin"    ;Файл для патча
$point = 0x10           ;Точка входа в файл (17 символ)
$size = 0xff            ;Количество изменяемых байт (255)
$Null = chr(0x00)       ;Заменяющий символ (обнуление)
$openfile = FileOpen($file, 16+1)
FileSetPos($openfile, $point, $FILE_BEGIN)
For $i = 0 to $size
    $string &= $Null
Next
FileWrite($openfile, $string)


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

AZJIO

Меценат
Меценат
Сообщения
2,879
Репутация
1,194
Black_Hole
ключевая переменная, она как бы есть, но в тоже время ее и нет, она пустая пока к ней не будет добавлена информация.
Зачем это мне говорить? Я знаю что это, с единственной разницей, Dim обычно вообще не используется, редкий случай для массива, чтобы очистить его содержимое, в остальных случаях это вполне конкретная область видимости, локальная или глобальная, а не двусмысленная.

(некогда не поверю что сложение 255 байт в строку и запись в файл одной строкой будет медленнее, чем запись 255 символов по отдельности в файл)
придётся поверить что такое возможно. Вы открываете файл, но фактически инициализируете буфер в памяти. Данные записываются только когда буфер заполнен. Подробности смотрите в функции FileFlush, которая сбрасывает буфер без закрытия файла. В то время как в памяти вы многократно выделяете область для слияния, отсюда и тормоза. Я проверил скорость, запись в цикле проигрывает, но скорее всего из-за инициализации функции.
 
Автор
B

Black_Hole

Знающий
Сообщения
126
Репутация
11
AZJIO
пожалуйста, напишите ваш рабочий вариант, хотелось бы увидеть и проверить производительность.
 

AZJIO

Меценат
Меценат
Сообщения
2,879
Репутация
1,194
Black_Hole
Для указанного примера в 256 символов замены можно ничего не менять. Если потребуется забить нулями 200 Мб, то тут уже время. Я выше предложил вариант от Melba23, но так как он на 1 Мб уже вылетает, то можно обрабатывать партиями до максимально возможного.
 
Верх