В данной заметке размещена библиотека,
которая позволяет работать с двоичными файлами.
Немного теории
32 разрядные процессоры работают с данными, которые представлены в виде, вещественное число — это 8 байт, целое число — 4 байта (32 разряда),
а строка — это на каждый символ -один байт, в конце строки ноль (кодировка ACIIZ) или длина строки в начале.
В луа есть два вида данных — вещественные числа и строки. Целых чисел нет — они вещественные.
Внутреннее представление данных в луа осуществляется не в основных форматах, а гораздо сложнее — в виде структур, которые занимают больше места, чем 8 байт для вещественных или байт на символ для строк.
В луа данные хранятся в виде структур содержащих тип и два массива , один из которых хеш.
Когда Мы в луа сохраняем данные во внешний файл, то вещественные числа преобразуются в строки. Т е во внешних файлах в луа данные всегда хранятся в виде строк.
Поэтому во внешние файлы в луа данные можно вывести лишь в текстовом виде.
Вещественное число имеет точность 15 десятичных цифр плюс еще порядок 5 цифр.
Таким образом, если выводим максимальное вещественное число, то в файле целые числа могут занять до 15 байт, а вещественные до 20 байт. В сравнении со стандарным способом это примерно в три раза больше места занимает.
Кроме того, когда мы пишем в файл данные оператором file:write(x), то луа проверяет тип и преобразует в строку по формату для записи в файл .
Так вот, я написал и выложил модуль для луа для работы с двоичными файлами.
Т е в эти файлы вещественное число пишется в 8 байт, целое в 4 байта, а строки либо в формате ASCIIZ либо в формате с явной длиной.
В результате получилось, что запись в файл чисел происходит в 4-6 раз быстрее.
Кроме того, файлы с числами имеют упорядоченную структуру, поэтому можно в луа осуществлять произвольный доступ к данным в файле.
Т е использовать файлы как массивы неограниченного размера.
В библиотеке реализованы следующие функции:
open(имя,режим) — открыть файл
close() -закрыть файл
getf(x) -записать вещественное число
x=setf() —прочитать вещественное число
geti (x) — записать целое число
x=seti (x) — прочитать целое число
gets(S) -записать строку
S=sets() -прочитать строку
getsn(S) -записать строку
S=setsn() -прочитать строку
pos=getpos() -получить текущую позицию
setpos(pos) -yстановить текущую позицию
seek(off,org) -переместить текущую позицию
flush () -сбросить данные на диск
lenf () — получить длину файла в байтах
Пример теста:
d1=»C:/»; — устройство
package.cpath =d1..»dll_lib/?.dll;»..package.cpath — путь к библиотеке
—————-
require «nklib» —— загрузка библиотеки
x=1000;
N=100000000;
—————————————-запись в текстовый файл
local nfile2=»C:/NK/testbin.txt»;
local file=io.open(nfile2,»wt»);
local t1=os.clock ()
local k=1; while (N>k) do file:write(tonumber(x)); k=k+1; end
local t2=os.clock ()
t3=os.difftime (t2,t1);
file:close();
print(t3);
—————————————-запись в двоичный файл
nfile=»C:/NK/testbin.bin»;
nklib.open(nfile,»w+»);
local t1=os.clock ()
local k=1; while (N>k) do nklib.seti(x); k=k+1; end
local t2=os.clock ()
t3=os.difftime (t2,t1);
nklib.close();
print(t3);
———————————
Работа с двоичными файлами примерно в 4-6 раз быстрее, чем с текстовыми.
Двоичные файлы можно использовать в качестве больших массивов с произвольным доступом.
Библиотеку можно взять здесь: NKlib