{
FileIO – модуль файлового ввода-вывода.
Copyright © 2017 Малик Разработчик
Это свободная программа: вы можете перераспространять её и/или
изменять её на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.
Эта программа распространяется в надежде, что она может быть полезна,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЁННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
общественной лицензии GNU.
Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<http://www.gnu.org/licenses/>.
}
unit FileIO;
{$MODE DELPHI,EXTENDEDSYNTAX ON}
interface
uses
Lang,
{$IF DEFINED(GO32V2)} IntfGo32
{$ELSEIF DEFINED(WINDOWS)} IntfWin
{$ENDIF}, IOStream, VFS;
{$ASMMODE INTEL,CALLING REGISTER,INLINE ON,GOTO ON}
{$H+,I-,J-,M-,Q-,R-,T-}
type
FileInputStream = class;
FileOutputStream = class;
FileStream = class;
LocalFileSystem = class;
FileInputStream = class(InputStream)
public
constructor create(const osFileName: UnicodeString);
procedure close(); override;
function seekSupported(): boolean; override;
function seek(delta: long): long; override;
function size(): long; override;
function position(): long; override;
function read(): int; overload; override;
function read(const dst: byte_Array1d; offset, length: int): int; overload; override;
function hasOpenError(): boolean; virtual;
procedure checkOpenError(); virtual;
strict private
closed: boolean;
error: int;
block: byte_Array1d;
blockPosition: short;
blockSize: short;
filePosition: long;
fileSize: long;
fileID: OSIntfFileOpenID;
function readFile(position: long): boolean;
end;
FileOutputStream = class(OutputStream)
public
constructor create(const osFileName: UnicodeString; appending: boolean);
procedure close(); override;
procedure flush(); override;
function write(value: int): boolean; overload; override;
function write(const src: byte_Array1d; offset, length: int): int; overload; override;
function hasOpenError(): boolean; virtual;
procedure checkOpenError(); virtual;
strict private
closed: boolean;
error: int;
block: byte_Array1d;
blockSize: short;
fileID: OSIntfFileOpenID;
function writeFile(): boolean;
end;
FileStream = class(InputOutputStream)
private
const ERROR_NO_ERROR = 0;
const ERROR_OPEN_ERROR = 1;
const ERROR_FILE_NAME_NOT_SPECIFIED = 2;
const DEFAULT_BLOCK_SIZE = $1000;
public
constructor create(const osFileName: UnicodeString);
procedure close(); override;
procedure flush(); override;
function seekSupported(): boolean; override;
function seek(delta: long): long; override;
function size(): long; override;
function position(): long; override;
function read(): int; overload; override;
function read(const dst: byte_Array1d; offset, length: int): int; overload; override;
function write(value: int): boolean; overload; override;
function write(const src: byte_Array1d; offset, length: int): int; overload; override;
procedure truncate(); override;
function hasOpenError(): boolean; virtual;
procedure checkOpenError(); virtual;
strict private
closed: boolean;
error: int;
block: byte_Array1d;
blockRewrited: boolean;
blockPosition: short;
blockSize: short;
filePosition: long;
fileSize: long;
fileID: OSIntfFileOpenID;
function readFile(position: long): boolean;
function writeFile(): boolean;
end;
LocalFileSystem = class(RefCountInterfacedObject, VirtualFileSystemReadOnly,
VirtualFileSystemReadWrite)
public
class function getInstance(): VirtualFileSystemReadWrite;
private
class procedure clinit();
class procedure cldone();
class procedure timeToOSIntf(const internal: long; out osintf: OSIntfDateTimeRecord);
class function timeToInternal(const osintf: OSIntfDateTimeRecord): long;
strict private
class var INSTANCE: VirtualFileSystemReadWrite;
public
constructor create();
procedure readAttributes(const fileOrDirName: UnicodeString;
attrDst: FileAttributes); virtual;
function fileNameCorrect(const fileOrDirName: UnicodeString): boolean; virtual;
function fileNameCaseSensitive(): boolean; virtual;
function fileNameMaximumLength(): int; virtual;
function findFirst(): FileEnumerator; overload; virtual;
function findFirst(const pathOrFileName: UnicodeString): FileEnumerator; overload; virtual;
function openFileForRead(const fileName: UnicodeString): InputStream; virtual;
procedure writeAttributes(const fileOrDirName: UnicodeString;
attrSrc: FileAttributes); virtual;
procedure move(const oldFileOrDirName, newFileOrDirName: UnicodeString); virtual;
procedure deleteDirectory(const dirName: UnicodeString); virtual;
procedure createDirectory(const dirName: UnicodeString); virtual;
procedure deleteFile(const fileName: UnicodeString); virtual;
function createFile(const fileName: UnicodeString): OutputStream; virtual;
function openFileForAppending(const fileName: UnicodeString): OutputStream; virtual;
function openFileForReadWrite(const fileName: UnicodeString): InputOutputStream; virtual;
end;
resourcestring
msgFileOpenError = 'Ошибка при открытии файла.';
msgFileNameNotSpecified = 'Имя файла не задано.';
msgFileAlreadyClosed = 'Файл уже был закрыт раннее.';
msgFileFailedRead = 'Не удалось прочитать данные из файла.';
msgFileFailedWrite = 'Не удалось записать данные в файл.';
msgFileFailedReadAttributes = 'Не удалось прочитать атрибуты файла.';
msgFileFailedWriteAttributes = 'Не удалось записать атрибуты файла.';
msgFileFailedMoveOrRename = 'Не удалось переместить и/или переименовать файл.';
msgFileFailedDelete = 'Не удалось удалить файл.';
msgDirectoryFailedCreate = 'Не удалось создать папку.';
msgDirectoryFailedDelete = 'Не удалось удалить папку.';
implementation
type
OSFileEnumerator = class(FileEnumerator)
public
constructor create(const findInfo: OSIntfFileFindInfo);
procedure close(); override;
function findNext(): boolean; override;
strict private
findInfo: OSIntfFileFindInfo;
procedure assignAttributes(); overload;
end;
{ FileInputStream }
constructor FileInputStream.create(const osFileName: UnicodeString);
begin
inherited create();
if length(osFileName) <= 0 then begin
self.error := FileStream.ERROR_FILE_NAME_NOT_SPECIFIED;
exit;
end;
if osintfFileOpenForReadOnly(osFileName, self.fileID) = false then begin
self.error := FileStream.ERROR_OPEN_ERROR;
exit;
end;
self.closed := false;
self.error := FileStream.ERROR_NO_ERROR;
self.block := byte_Array1d_create(FileStream.DEFAULT_BLOCK_SIZE);
self.blockPosition := 0;
self.blockSize := 0;
self.filePosition := -1;
self.fileSize := osintfFileGetSize(self.fileID);
readFile(0);
end;
procedure FileInputStream.close();
begin
checkOpenError();
if osintfFileClose(fileID) then begin
closed := true;
end;
end;
function FileInputStream.seekSupported(): boolean;
begin
result := (error = 0) and (closed = false);
end;
function FileInputStream.seek(delta: long): long;
begin
checkOpenError();
result := Math.max(0, Math.min(filePosition + blockPosition + delta, fileSize));
if readFile(result and (-FileStream.DEFAULT_BLOCK_SIZE)) = false then begin
raise IOException.create(msgFileFailedRead);
end;
blockPosition := int(result) and (FileStream.DEFAULT_BLOCK_SIZE - 1);
end;
function FileInputStream.size(): long;
begin
checkOpenError();
result := fileSize;
end;
function FileInputStream.position(): long;
begin
checkOpenError();
result := filePosition + blockPosition;
end;
function FileInputStream.read(): int;
var
bsiz: int;
bpos: int;
begin
checkOpenError();
result := -1;
bsiz := blockSize;
bpos := blockPosition;
if bpos >= bsiz then begin
exit;
end;
result := block[bpos] and $ff;
inc(bpos);
blockPosition := short(bpos);
if (bpos >= bsiz) and (readFile(filePosition + bsiz) = false) then begin
raise IOException.create(msgFileFailedRead);
end;
end;
function FileInputStream.read(const dst: byte_Array1d; offset, length: int): int;
var
lim: int;
len: int;
bsiz: int;
bpos: int;
reading: int;
remaining: int;
block: byte_Array1d;
begin
checkOpenError();
lim := offset + length;
len := System.length(dst);
if (lim > len) or (lim < offset) or (offset > len) or (offset < 0) then begin
raise ArrayIndexOutOfBoundsException.create(msgArrayIndexOutOfBounds);
end;
result := 0;
remaining := length;
block := self.block;
while remaining > 0 do begin
bsiz := blockSize;
bpos := blockPosition;
reading := Math.min(bsiz - bpos, remaining);
if reading = 0 then begin
exit;
end;
arraycopyPrimitives(block, bpos, dst, offset, reading);
inc(bpos, reading);
inc(offset, reading);
inc(result, reading);
dec(remaining, reading);
blockPosition := short(bpos);
if (bpos >= bsiz) and (readFile(filePosition + bsiz) = false) then begin
raise IOException.create(msgFileFailedRead);
end;
end;
end;
function FileInputStream.hasOpenError(): boolean;
begin
result := (error <> 0) or (closed <> false);
end;
procedure FileInputStream.checkOpenError();
begin
case error of
FileStream.ERROR_NO_ERROR: begin
if closed then begin
raise IOException.create(msgFileAlreadyClosed);
end;
end;
FileStream.ERROR_OPEN_ERROR: begin
raise IOException.create(msgFileOpenError);
end;
FileStream.ERROR_FILE_NAME_NOT_SPECIFIED: begin
raise IOException.create(msgFileNameNotSpecified);
end;
end;
end;
function FileInputStream.readFile(position: long): boolean;
var
must: int;
readed: int;
begin
blockPosition := 0;
if filePosition = position then begin
result := true;
exit;
end;
position := osintfFileSetPos(fileID, position);
must := int(Math.min(fileSize - position, FileStream.DEFAULT_BLOCK_SIZE));
if must > 0 then begin
readed := osintfFileRead(fileID, @(block[0]), FileStream.DEFAULT_BLOCK_SIZE);
end else begin
readed := 0;
end;
blockSize := short(readed);
filePosition := position;
result := readed >= must;
end;
{ FileOutputStream }
constructor FileOutputStream.create(const osFileName: UnicodeString; appending: boolean);
var
osintfFileOpenFuntion: function (const osFileName: UnicodeString;
out fileID: OSIntfFileOpenID): boolean;
begin
inherited create();
if appending then begin
osintfFileOpenFuntion := osintfFileOpenForAppending;
end else begin
osintfFileOpenFuntion := osintfFileCreate;
end;
if length(osFileName) <= 0 then begin
self.error := FileStream.ERROR_FILE_NAME_NOT_SPECIFIED;
exit;
end;
if osintfFileOpenFuntion(osFileName, self.fileID) = false then begin
self.error := FileStream.ERROR_OPEN_ERROR;
exit;
end;
self.closed := false;
self.error := FileStream.ERROR_NO_ERROR;
self.block := byte_Array1d_create(FileStream.DEFAULT_BLOCK_SIZE);
self.blockSize := 0;
end;
procedure FileOutputStream.close();
var
writed: boolean;
begin
checkOpenError();
writed := writeFile();
if osintfFileClose(fileID) then begin
closed := true;
end;
if writed = false then begin
raise IOException.create(msgFileFailedWrite);
end;
end;
procedure FileOutputStream.flush();
begin
checkOpenError();
if writeFile() = false then begin
raise IOException.create(msgFileFailedWrite);
end;
end;
function FileOutputStream.write(value: int): boolean;
var
bsiz: int;
begin
checkOpenError();
bsiz := blockSize;
block[bsiz] := byte(value);
inc(bsiz);
blockSize := short(bsiz);
if (bsiz >= FileStream.DEFAULT_BLOCK_SIZE) and (writeFile() = false) then begin
raise IOException.create(msgFileFailedWrite);
end;
result := true;
end;
function FileOutputStream.write(const src: byte_Array1d; offset, length: int): int;
var
lim: int;
len: int;
bsiz: int;
writing: int;
remaining: int;
block: byte_Array1d;
begin
checkOpenError();
lim := offset + length;
len := System.length(src);
if (lim > len) or (lim < offset) or (offset > len) or (offset < 0) then begin
raise ArrayIndexOutOfBoundsException.create(msgArrayIndexOutOfBounds);
end;
result := 0;
remaining := length;
block := self.block;
while remaining > 0 do begin
bsiz := blockSize;
writing := Math.min(FileStream.DEFAULT_BLOCK_SIZE - bsiz, remaining);
if writing = 0 then begin
exit;
end;
arraycopyPrimitives(src, offset, block, bsiz, writing);
inc(bsiz, writing);
inc(offset, writing);
inc(result, writing);
dec(remaining, writing);
blockSize := short(bsiz);
if (bsiz >= FileStream.DEFAULT_BLOCK_SIZE) and (writeFile() = false) then begin
raise IOException.create(msgFileFailedWrite);
end;
end;
end;
function FileOutputStream.hasOpenError(): boolean;
begin
result := (error <> 0) or (closed <> false);
end;
procedure FileOutputStream.checkOpenError();
begin
case error of
FileStream.ERROR_NO_ERROR: begin
if closed then begin
raise IOException.create(msgFileAlreadyClosed);
end;
end;
FileStream.ERROR_OPEN_ERROR: begin
raise IOException.create(msgFileOpenError);
end;
FileStream.ERROR_FILE_NAME_NOT_SPECIFIED: begin
raise IOException.create(msgFileNameNotSpecified);
end;
end;
end;
function FileOutputStream.writeFile(): boolean;
var
bsiz: int;
begin
bsiz := blockSize;
if bsiz <= 0 then begin
result := true;
exit;
end;
blockSize := 0;
result := osintfFileWrite(fileID, @(block[0]), bsiz) >= bsiz;
end;
{ FileStream }
constructor FileStream.create(const osFileName: UnicodeString);
begin
inherited create();
if length(osFileName) <= 0 then begin
self.error := FileStream.ERROR_FILE_NAME_NOT_SPECIFIED;
exit;
end;
if osintfFileOpenForReadWrite(osFileName, self.fileID) = false then begin
self.error := FileStream.ERROR_OPEN_ERROR;
exit;
end;
self.closed := false;
self.error := FileStream.ERROR_NO_ERROR;
self.block := byte_Array1d_create(FileStream.DEFAULT_BLOCK_SIZE);
self.blockRewrited := false;
self.blockPosition := 0;
self.blockSize := 0;
self.filePosition := -1;
self.fileSize := osintfFileGetSize(self.fileID);
readFile(0);
end;
procedure FileStream.close();
var
writed: boolean;
begin
checkOpenError();
writed := writeFile();
if osintfFileClose(fileID) then begin
closed := true;
end;
if writed = false then begin
raise IOException.create(msgFileFailedWrite);
end;
end;
procedure FileStream.flush();
begin
checkOpenError();
if writeFile() = false then begin
raise IOException.create(msgFileFailedWrite);
end;
end;
function FileStream.seekSupported(): boolean;
begin
result := (error = 0) and (closed = false);
end;
function FileStream.seek(delta: long): long;
begin
checkOpenError();
result := Math.max(0, Math.min(filePosition + blockPosition + delta, fileSize));
if (writeFile() = false) or
(readFile(result and (-FileStream.DEFAULT_BLOCK_SIZE)) = false) then begin
raise IOException.create(msgFileFailedRead);
end;
blockPosition := int(result) and (FileStream.DEFAULT_BLOCK_SIZE - 1);
end;
function FileStream.size(): long;
begin
checkOpenError();
result := fileSize;
end;
function FileStream.position(): long;
begin
checkOpenError();
result := filePosition + blockPosition;
end;
function FileStream.read(): int;
var
bsiz: int;
bpos: int;
begin
checkOpenError();
result := -1;
bsiz := blockSize;
bpos := blockPosition;
if bpos >= bsiz then begin
exit;
end;
result := block[bpos] and $ff;
inc(bpos);
blockPosition := short(bpos);
if (bpos >= bsiz) and
((writeFile() = false) or (readFile(filePosition + bsiz) = false)) then begin
raise IOException.create(msgFileFailedRead);
end;
end;
function FileStream.read(const dst: byte_Array1d; offset, length: int): int;
var
lim: int;
len: int;
bsiz: int;
bpos: int;
reading: int;
remaining: int;
block: byte_Array1d;
begin
checkOpenError();
lim := offset + length;
len := System.length(dst);
if (lim > len) or (lim < offset) or (offset > len) or (offset < 0) then begin
raise ArrayIndexOutOfBoundsException.create(msgArrayIndexOutOfBounds);
end;
result := 0;
remaining := length;
block := self.block;
while remaining > 0 do begin
bsiz := blockSize;
bpos := blockPosition;
reading := Math.min(bsiz - bpos, remaining);
if reading = 0 then begin
exit;
end;
arraycopyPrimitives(block, bpos, dst, offset, reading);
inc(bpos, reading);
inc(offset, reading);
inc(result, reading);
dec(remaining, reading);
blockPosition := short(bpos);
if (bpos >= bsiz) and
((writeFile() = false) or (readFile(filePosition + bsiz) = false)) then begin
raise IOException.create(msgFileFailedRead);
end;
end;
end;
function FileStream.write(value: int): boolean;
var
bpos: int;
fpos: long;
begin
checkOpenError();
bpos := blockPosition;
block[bpos] := byte(value);
inc(bpos);
blockRewrited := true;
blockPosition := short(bpos);
fpos := filePosition + bpos;
if blockSize < bpos then begin
blockSize := short(bpos);
end;
if fileSize < fpos then begin
fileSize := fpos;
end;
if (bpos >= FileStream.DEFAULT_BLOCK_SIZE) and
((writeFile() = false) or (readFile(fpos) = false)) then begin
raise IOException.create(msgFileFailedWrite);
end;
result := true;
end;
function FileStream.write(const src: byte_Array1d; offset, length: int): int;
var
lim: int;
len: int;
bpos: int;
writing: int;
remaining: int;
fpos: long;
block: byte_Array1d;
begin
checkOpenError();
lim := offset + length;
len := System.length(src);
if (lim > len) or (lim < offset) or (offset > len) or (offset < 0) then begin
raise ArrayIndexOutOfBoundsException.create(msgArrayIndexOutOfBounds);
end;
result := 0;
remaining := length;
block := self.block;
while remaining > 0 do begin
bpos := blockPosition;
writing := Math.min(FileStream.DEFAULT_BLOCK_SIZE - bpos, remaining);
if writing = 0 then begin
exit;
end;
arraycopyPrimitives(src, offset, block, bpos, writing);
inc(bpos, writing);
inc(offset, writing);
inc(result, writing);
dec(remaining, writing);
blockRewrited := true;
blockPosition := short(bpos);
fpos := filePosition + bpos;
if blockSize < bpos then begin
blockSize := short(bpos);
end;
if fileSize < fpos then begin
fileSize := fpos;
end;
if (bpos >= FileStream.DEFAULT_BLOCK_SIZE) and
((writeFile() = false) or (readFile(fpos) = false)) then begin
raise IOException.create(msgFileFailedWrite);
end;
end;
end;
procedure FileStream.truncate();
var
bpos: int;
fpos: long;
begin
checkOpenError();
bpos := blockPosition;
fpos := filePosition + bpos;
blockSize := short(bpos);
fileSize := fpos;
osintfFileSetPos(fileID, fpos);
osintfFileSetSize(fileID);
end;
function FileStream.hasOpenError(): boolean;
begin
result := (error <> 0) or (closed <> false);
end;
procedure FileStream.checkOpenError();
begin
case error of
FileStream.ERROR_NO_ERROR: begin
if closed then begin
raise IOException.create(msgFileAlreadyClosed);
end;
end;
FileStream.ERROR_OPEN_ERROR: begin
raise IOException.create(msgFileOpenError);
end;
FileStream.ERROR_FILE_NAME_NOT_SPECIFIED: begin
raise IOException.create(msgFileNameNotSpecified);
end;
end;
end;
function FileStream.readFile(position: long): boolean;
var
must: int;
readed: int;
begin
blockPosition := 0;
if filePosition = position then begin
result := true;
exit;
end;
position := osintfFileSetPos(fileID, position);
must := int(Math.min(fileSize - position, FileStream.DEFAULT_BLOCK_SIZE));
if must > 0 then begin
readed := osintfFileRead(fileID, @(block[0]), must);
end else begin
readed := 0;
end;
blockSize := short(readed);
blockRewrited := false;
filePosition := position;
result := readed >= must;
end;
function FileStream.writeFile(): boolean;
var
bsiz: int;
begin
bsiz := blockSize;
if (blockRewrited = false) or (bsiz <= 0) then begin
result := true;
exit;
end;
blockRewrited := false;
osintfFileSetPos(fileID, filePosition);
result := osintfFileWrite(fileID, @(block[0]), bsiz) >= bsiz;
end;
{ LocalFileSystem }
class function LocalFileSystem.getInstance(): VirtualFileSystemReadWrite;
begin
result := INSTANCE;
end;
class procedure LocalFileSystem.clinit();
begin
INSTANCE := LocalFileSystem.create();
end;
class procedure LocalFileSystem.cldone();
begin
INSTANCE := nil;
end;
class procedure LocalFileSystem.timeToOSIntf(const internal: long;
out osintf: OSIntfDateTimeRecord);
var
millis: int;
begin
millis := internal.shorts[0] and $ffff;
osintf.year := internal.shorts[3] and $ffff;
osintf.month := internal.bytes[5];
osintf.day := internal.bytes[4];
osintf.reserved := 0;
osintf.hour := internal.bytes[3];
osintf.minute := internal.bytes[2];
osintf.second := millis div 1000;
osintf.millis := millis mod 1000;
end;
class function LocalFileSystem.timeToInternal(const osintf: OSIntfDateTimeRecord): long;
begin
result := longBuild(osintf.year, (osintf.month shl 8) + (osintf.day and $ff),
(osintf.hour shl 8) + (osintf.minute and $ff), osintf.second * 1000 + osintf.millis);
end;
constructor LocalFileSystem.create();
begin
inherited create();
end;
procedure LocalFileSystem.readAttributes(const fileOrDirName: UnicodeString;
attrDst: FileAttributes);
var
attributes: int;
creationTime: OSIntfDateTimeRecord;
lastWriteTime: OSIntfDateTimeRecord;
lastAccessTime: OSIntfDateTimeRecord;
begin
if attrDst = nil then begin
raise NullPointerException.create(msgNullPointer);
end;
if osintfFileReadAttributes(osintfFileNameToOS(fileOrDirName), attributes,
creationTime, lastWriteTime, lastAccessTime) = false then begin
raise IOException.create(msgFileFailedReadAttributes);
end;
attrDst.assignAttributes(attributes, timeToInternal(creationTime),
timeToInternal(lastWriteTime), timeToInternal(lastAccessTime));
end;
function LocalFileSystem.fileNameCorrect(const fileOrDirName: UnicodeString): boolean;
begin
result := osintfFileNameValid(osintfFileNameToOS(fileOrDirName));
end;
function LocalFileSystem.fileNameCaseSensitive(): boolean;
begin
result := osintfFileNameCaseSensitive();
end;
function LocalFileSystem.fileNameMaximumLength(): int;
begin
result := osintfFileNameMaximumLength();
end;
function LocalFileSystem.findFirst(): FileEnumerator;
var
findInfo: OSIntfFileFindInfo;
begin
if osintfFileFindFirst(osintfFileNameToOS('/'), findInfo) = false then begin
result := nil;
exit;
end;
result := OSFileEnumerator.create(findInfo);
end;
function LocalFileSystem.findFirst(const pathOrFileName: UnicodeString): FileEnumerator;
var
findInfo: OSIntfFileFindInfo;
begin
if osintfFileFindFirst(osintfFileNameToOS(pathOrFileName), findInfo) = false then begin
result := nil;
exit;
end;
result := OSFileEnumerator.create(findInfo);
end;
function LocalFileSystem.openFileForRead(const fileName: UnicodeString): InputStream;
begin
result := FileInputStream.create(osintfFileNameToOS(fileName));
try
FileInputStream(result).checkOpenError();
except
result.free();
raise;
end;
end;
procedure LocalFileSystem.writeAttributes(const fileOrDirName: UnicodeString;
attrSrc: FileAttributes);
var
attributes: int;
creationTime: OSIntfDateTimeRecord;
lastWriteTime: OSIntfDateTimeRecord;
lastAccessTime: OSIntfDateTimeRecord;
begin
if attrSrc = nil then begin
raise NullPointerException.create(msgNullPointer);
end;
attributes := attrSrc.flags;
timeToOSIntf(attrSrc.creationTime, creationTime);
timeToOSIntf(attrSrc.lastWriteTime, lastWriteTime);
timeToOSIntf(attrSrc.lastAccessTime, lastAccessTime);
if osintfFileWriteAttributes(osintfFileNameToOS(fileOrDirName), attributes,
creationTime, lastWriteTime, lastAccessTime) = false then begin
raise IOException.create(msgFileFailedWriteAttributes);
end;
end;
procedure LocalFileSystem.move(const oldFileOrDirName, newFileOrDirName: UnicodeString);
begin
if osintfFileMove(osintfFileNameToOS(oldFileOrDirName),
osintfFileNameToOS(newFileOrDirName)) = false then begin
raise IOException.create(msgFileFailedMoveOrRename);
end;
end;
procedure LocalFileSystem.deleteDirectory(const dirName: UnicodeString);
begin
if osintfDirectoryDelete(osintfFileNameToOS(dirName)) = false then begin
raise IOException.create(msgDirectoryFailedDelete);
end;
end;
procedure LocalFileSystem.createDirectory(const dirName: UnicodeString);
begin
if osintfDirectoryDelete(osintfFileNameToOS(dirName)) = false then begin
raise IOException.create(msgDirectoryFailedCreate);
end;
end;
procedure LocalFileSystem.deleteFile(const fileName: UnicodeString);
begin
if osintfFileDelete(osintfFileNameToOS(fileName)) = false then begin
raise IOException.create(msgFileFailedDelete);
end;
end;
function LocalFileSystem.createFile(const fileName: UnicodeString): OutputStream;
begin
result := FileOutputStream.create(osintfFileNameToOS(fileName), false);
try
FileOutputStream(result).checkOpenError();
except
result.free();
raise;
end;
end;
function LocalFileSystem.openFileForAppending(const fileName: UnicodeString): OutputStream;
begin
result := FileOutputStream.create(osintfFileNameToOS(fileName), true);
try
FileOutputStream(result).checkOpenError();
except
result.free();
raise;
end;
end;
function LocalFileSystem.openFileForReadWrite(const fileName: UnicodeString): InputOutputStream;
begin
result := FileStream.create(osintfFileNameToOS(fileName));
try
FileStream(result).checkOpenError();
except
result.free();
raise;
end;
end;
{ OSFileEnumerator }
constructor OSFileEnumerator.create(const findInfo: OSIntfFileFindInfo);
begin
inherited create();
self.findInfo := findInfo;
assignAttributes();
end;
procedure OSFileEnumerator.close();
begin
osintfFileFindClose(findInfo);
end;
function OSFileEnumerator.findNext(): boolean;
begin
if osintfFileFindNext(findInfo) = false then begin
result := false;
exit;
end;
assignAttributes();
result := true;
end;
procedure OSFileEnumerator.assignAttributes();
begin
with findInfo do begin
assignAttributes(attributes,
LocalFileSystem.timeToInternal(creationTime),
LocalFileSystem.timeToInternal(lastWriteTime),
LocalFileSystem.timeToInternal(lastAccessTime),
size, osintfFileNameToVFS(name));
end;
end;
initialization
LocalFileSystem.clinit();
finalization
LocalFileSystem.cldone();
end.