Как открыть файл в эксклюз. режиме, чтобы затем скопир. его?
От: Fortnum  
Дата: 20.09.06 08:19
Оценка:
Надо заблокировать файл C:\MyPath\MyFile.xxx, чтобы никто не мог его открыть ни на чтение, ни на запись. Затем скопировать его во временный файл — какой-нибудь там C:\Temp\AnyName.yyy, после чего внести в этот временный файл кое-какие изменения, и если изменения внесены были успешно, скопировать его назад с overwrite`ом, после чего исходный файл (с внесенными изменениями) разблокировать для общего доступа, а временный файл удалить. Если изменения внести не удается, временный файл удаляется, а исходный разблокируется. Как это сделать?

Пояснения, что я пытаюсь сделать:

string sourcePath = "C:\MyPath\MyFile.xxx";
string destPath = Path.GetTempFileName();

FileStream origDb = File.Open(sourcePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None);

File.Copy(sourcePath, destPath, true);

...


На File.Copy вылетает exception, причем странного какого-то типа — такое впечатление, что я временный файл залочил, хотя на самом деле я залочил исходный файл::


System.IO.IOException: The process cannot access the file "C:\DOCUME~1\9335~1\LOCALS~1\Temp\tmp3.tmp" because it is being used by another process.


Если первую строчку File.Open( ... ) закоментировать — все ОК получается, но во время изменений временного файла, кто-то может что-то дописать в оригинальный — так не пойдет.
Re: Как открыть файл в эксклюз. режиме, чтобы затем скопир.
От: Pavel M. Россия  
Дата: 20.09.06 08:50
Оценка:
Здравствуйте, Fortnum, Вы писали:

F>Надо заблокировать файл C:\MyPath\MyFile.xxx, чтобы никто не мог его открыть ни на чтение, ни на запись. Затем скопировать его во временный файл — какой-нибудь там C:\Temp\AnyName.yyy, после чего внести в этот временный файл кое-какие изменения, и если изменения внесены были успешно, скопировать его назад с overwrite`ом, после чего исходный файл (с внесенными изменениями) разблокировать для общего доступа, а временный файл удалить. Если изменения внести не удается, временный файл удаляется, а исходный разблокируется. Как это сделать?


F>Пояснения, что я пытаюсь сделать:


F>
F>string sourcePath = "C:\MyPath\MyFile.xxx";
F>string destPath = Path.GetTempFileName();

F>FileStream origDb = File.Open(sourcePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None);

F>File.Copy(sourcePath, destPath, true);

F>...

F>


F>На File.Copy вылетает exception, причем странного какого-то типа — такое впечатление, что я временный файл залочил, хотя на самом деле я залочил исходный файл::



F>

F>System.IO.IOException: The process cannot access the file "C:\DOCUME~1\9335~1\LOCALS~1\Temp\tmp3.tmp" because it is being used by another process.


F>Если первую строчку File.Open( ... ) закоментировать — все ОК получается, но во время изменений временного файла, кто-то может что-то дописать в оригинальный — так не пойдет.


поставь строчку с копией ниже Open.
--------------------------
less think — do more
Re[2]: Как открыть файл в эксклюз. режиме, чтобы затем скопи
От: Fortnum  
Дата: 20.09.06 09:04
Оценка:
Здравствуйте, Pavel M., Вы писали:

PM>поставь строчку с копией ниже Open.


Не понял — она и стоит ниже Open.
Re[3]: Как открыть файл в эксклюз. режиме, чтобы затем скопи
От: Pavel M. Россия  
Дата: 20.09.06 10:47
Оценка:
Здравствуйте, Fortnum, Вы писали:

F>Здравствуйте, Pavel M., Вы писали:


PM>>поставь строчку с копией ниже Open.


F>Не понял — она и стоит ниже Open.


в смысле, выше =)
Copy
Open

Файлик скопируется и сразу заблокируется!
--------------------------
less think — do more
Re[4]: Как открыть файл в эксклюз. режиме, чтобы затем скопи
От: Fortnum  
Дата: 20.09.06 10:56
Оценка:
Здравствуйте, Pavel M., Вы писали:

PM>в смысле, выше =)

PM>Copy
PM>Open

PM>Файлик скопируется и сразу заблокируется!


Не, так не пойдет — а что если сразу после окончания команды Copy, но до начала исполнения команды Open, какой-нибудь клиент изменит что-нибудь в этом файле? Его изменения будут потеряны.
Re[5]: Как открыть файл в эксклюз. режиме, чтобы затем скопи
От: Brick_1 Украина  
Дата: 20.09.06 11:11
Оценка: 2 (1)
Здравствуйте, Fortnum, Вы писали:

F>Здравствуйте, Pavel M., Вы писали:


PM>>в смысле, выше =)

PM>>Copy
PM>>Open

PM>>Файлик скопируется и сразу заблокируется!


F>Не, так не пойдет — а что если сразу после окончания команды Copy, но до начала исполнения команды Open, какой-нибудь клиент изменит что-нибудь в этом файле? Его изменения будут потеряны.


Доброго!
Копируй не штатной функцией, а сам,например так..

private bool copyFile(string fromFile,string toFile,bool delAfterCopy)
{
Encoding enc866;
FileStream fileToRead=null;
FileStream fileToWrite=null;
BinaryWriter bw;
BinaryReader br;
Int64 fileLength=0;
try
{
enc866=Encoding.GetEncoding(866);

fileToRead=File.Open(fromFile,FileMode.Open,FileAccess.ReadWrite,FileShare.None);
fileLength=fileToRead.Length;
br=new BinaryReader(fileToRead,enc866);
fileToRead.Seek(0,SeekOrigin.Begin);
Byte[] byteToRead=new Byte[fileLength];
if(br.Read(byteToRead,0,(int)fileLength)!=fileLength)
{
fileToRead.Close();
fileToRead=null;
return false;
}
fileToWrite=File.Open(toFile,FileMode.OpenOrCreate,FileAccess.Write,FileShare.None);
fileToWrite.SetLength(0);
bw=new BinaryWriter(fileToWrite,enc866);
bw.Write(byteToRead,0,(int)fileLength);
fileToWrite.Close();
fileToWrite=null;
// Сделал нулевого размера после копирования
if(delAfterCopy)
fileToRead.SetLength(0);
fileToRead.Close();
fileToRead=null;
// Удалил после копирования
if(delAfterCopy)
File.Delete(fromFile);
}
catch(Exception e)
{
if(fileToRead!=null)
fileToRead.Close();
if(fileToWrite!=null)
fileToWrite.Close();
try{File.Delete(toFile);}catch{}
return false;
}
return true;
}
Re: Как открыть файл в эксклюз. режиме, чтобы затем скопир.
От: Аноним  
Дата: 20.09.06 11:35
Оценка:
Здравствуйте, Fortnum, Вы писали:

F>Надо заблокировать файл C:\MyPath\MyFile.xxx, чтобы никто не мог его открыть ни на чтение, ни на запись. Затем скопировать его во временный файл — какой-нибудь там C:\Temp\AnyName.yyy, после чего внести в этот временный файл кое-какие изменения, и если изменения внесены были успешно, скопировать его назад с overwrite`ом, после чего исходный файл (с внесенными изменениями) разблокировать для общего доступа, а временный файл удалить. Если изменения внести не удается, временный файл удаляется, а исходный разблокируется. Как это сделать?


Всё понял, одного не понял: *зачем вообще создавать временный файл*?
Лочишь исходный файл, вносишь изменения, разлочиваешь. В чём проблема-то?
Re[2]: Как открыть файл в эксклюз. режиме, чтобы затем скопи
От: Fortnum  
Дата: 20.09.06 12:28
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Всё понял, одного не понял: *зачем вообще создавать временный файл*?

А>Лочишь исходный файл, вносишь изменения, разлочиваешь. В чём проблема-то?

Г-н Аноним, вносимые изменения довольно сложные, и я не могу предсказать, что в процессе внесения изменений не возникнет ошибок. Если ошибка возникнет, надо будет сделать откат. Для этого и нужен новый временный файл — старый остается как резервная копия.

Кстати, простым копированием из FileStream в FileStream я эту проблему решил, но хотелось бы просто понять, как это сделать правильней? Ведь, по сути, я написал свою реализацию File.Copy — а зачем?..
Re[6]: Как открыть файл в эксклюз. режиме, чтобы затем скопи
От: Fortnum  
Дата: 20.09.06 12:32
Оценка:
Здравствуйте, Brick_1, Вы писали:

B_>Копируй не штатной функцией, а сам,например так..


B_> Byte[] byteToRead=new Byte[fileLength];


Вот-вот... а если файл занимает несколько Гб?.. ну это я так, чисто теоретически... Тогда своя функция File.Copy еще более усложнится... не хотелось бы изобретать велосипед, хотя особых напрягов в этом отношении нет Спасибо. Уже сам до этого додумался — работает.
Re: Как открыть файл в эксклюз. режиме, чтобы затем скопир.
От: AlexZu Россия  
Дата: 20.09.06 12:54
Оценка: 1 (1)
Здравствуйте, Fortnum, Вы писали:

F>Надо заблокировать файл C:\MyPath\MyFile.xxx, чтобы никто не мог его открыть ни на чтение, ни на запись.

Вот File.Copy и не может его открыть, поскольку для того чтобы скопировать файл должны быть доступ на чтение.
т.е. вы добились желаемого, чему же удивляться?
Подозреваю что вам достаточно запретить только запись в файл (FileShare.Read).

ps: а сообщение в исключение действительно ошибочное, бага в .NEt v1.1 (в .NET v2 все путем).
Re[3]: Как открыть файл в эксклюз. режиме, чтобы затем скопи
От: Аноним  
Дата: 20.09.06 13:27
Оценка:
Здравствуйте, Fortnum, Вы писали:

F>Г-н Аноним, вносимые изменения довольно сложные, и я не могу предсказать, что в процессе внесения изменений не возникнет ошибок. Если ошибка возникнет, надо будет сделать откат. Для этого и нужен новый временный файл — старый остается как резервная копия.


F>Кстати, простым копированием из FileStream в FileStream я эту проблему решил, но хотелось бы просто понять, как это сделать правильней? Ведь, по сути, я написал свою реализацию File.Copy — а зачем?..


Хорошо, если так, тогда самый правильный вариант, то, что называется "по уму", будет выглядеть так:

public class TransactFileStream : FileStream
{
  // хранит временные данные
  // помещённые через Append(...)
  object m_tempdata;

  // сохраняет временные данные,
  // которые будут добавлены при вызове Commit (...)
  public bool Append (object SomeData);

  // пишет (добавляет) данные из m_tempdata
  public bool Commit ();
  // просто очищает m_tempdata
  public bool Rollback ();
}


т.е. написание своего FileStream'а. Это универсальный, легко расширяемый вариант, и я бы выбрал именно его, но я бы ещё слегка модифицировал бы так, что внутри этого класса создавался бы ещё поток данных типа BufferedStream, и все данные при открытии оригинального файла считывались бы в этот самый буфер, а метод Commit() писал бы дополнения/изменения не в файл, а сначала в буфер, и только если запись в буфер успешна, тогда подменять данные файла, на данные в буфере.

Ещё вопрос: вы не пробовали рассмотреть в качестве файла для хранения базу данных? И обращаться к ней через System.Data.* ? Там же есть встроенные транзакции и т.п. Или задача не настолько серьёзная, чтобы применять Data?
Re[7]: Как открыть файл в эксклюз. режиме, чтобы затем скопи
От: Аноним  
Дата: 21.09.06 07:28
Оценка:
Здравствуйте, Fortnum, Вы писали:

F>Здравствуйте, Brick_1, Вы писали:


B_>>Копируй не штатной функцией, а сам,например так..


B_>> Byte[] byteToRead=new Byte[fileLength];


F>Вот-вот... а если файл занимает несколько Гб?.. ну это я так, чисто теоретически... Тогда своя функция File.Copy еще более усложнится... не хотелось бы изобретать велосипед, хотя особых напрягов в этом отношении нет Спасибо. Уже сам до этого додумался — работает.


Доброго !
Еще на старом добром досовском борланде практически все писали копирование файла блочно через блок заданного размера
Могу подогнать исходники заточишь под .net
С уважением
Re[8]: Как открыть файл в эксклюз. режиме, чтобы затем скопи
От: Fortnum  
Дата: 21.09.06 08:37
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Еще на старом добром досовском борланде практически все писали копирование файла блочно через блок заданного размера

А>Могу подогнать исходники заточишь под .net

А! Ну, все понятно теперь. Спасибо, таким макаром я уже сам справился
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.