Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 31.05.2016, 10:57   #1
URQq
Пользователь
 
Регистрация: 31.05.2016
Сообщений: 11
По умолчанию Небольшое затруднение с BlockWrite

Добрый день.

Возникла небольшая проблема с записью в нетипизированный двоичный файл.
Необходимо записать данные из таблицы в двоичный файл. Выделяем для этого в файле 8 байт. В свободные "нули", край правый.
Имеется таблица с данными.
Берём данные из таблицы и записываем в двоичный файл:

Код:
...
  Str := DBGrid1.DataSource.DataSet.FieldByName('Str').Text;
  AssignFile(myFile, SaveDialog2.FileName);
  ReWrite(myFile, 1);
  BlockWrite(myFile, Str[1], 8);
...
Если данные в таблице состоят из четырёх и более символов (ограничение 8), то в двоичном файле записывается всё верно.
Например: 05 05 05 05 00 00 00 00

Проблема возникает, когда менее четырёх символов в таблице. Появляется некий "мусор", неизвестные символы.
Например: 05 05 05 00 D0 4C F1 01 (необходимо: 05 05 05 00 00 00 00 00)

У меня два вопроса (может плохо искал, но гугл мне не помог):
1. Что это за символы (конец ячейки? конец строки? или где?)?
2. Как реализовать задачу правильно?

Спасибо.
URQq вне форума Ответить с цитированием
Старый 31.05.2016, 11:37   #2
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

Она и пишет 8 байт начиная с указанного адреса. Если строка короче, то справа будет мусор. Даже те нули для 4-х символов мусор, повезло просто.
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Старый 31.05.2016, 11:41   #3
Serge_Bliznykov
Старожил
 
Регистрация: 09.01.2008
Сообщений: 26,229
По умолчанию

Это мусор, который находится в памяти. Он там никому не мешает, т.к. в строке есть либо длина строки (это в начале строки или в управляющей структуре, Pascal-подобные строки), либо строка заканчивается нулём (C-подобные строки).

Теперь, что делать Вам. Если мусор Вам мешает, то Вы можете банально заполнять нулями строку:
Код:
while Length(s)<8 do s := s + #0;
если важна скорость, то можно взять обычный статический массив длиной 8 байт,
скинуть строку туда (через Move: Move(s[1], Buf, Length(s) * SizeOf(Char));
массив предварительно занулить.

Цитата:
2. Как реализовать задачу правильно?
что такое "правильно" - это Вам виднее!
вообще, я бы лично писал в файл сначала длину строки (Intgere), а потом полностью всё строку. Это позволило бы: 1) не заботиться о мусоре, которого там бы не было по определению 2) возможность писать пустые строки и строки длиной в сотни и тысячи символов

p.s. и вообще, зачем Вам олдскульный BlockWrite - чем Вас TFileStream не устраивает?!
Serge_Bliznykov вне форума Ответить с цитированием
Старый 31.05.2016, 11:54   #4
min@y™
Цифровой кот
Старожил
 
Аватар для min@y™
 
Регистрация: 29.08.2014
Сообщений: 7,629
По умолчанию

А тебе именно по 8 байт надо писать или от 0 до 8? Если размер блоков постоянный, то резонно юзать таки как раз типизированный файл.
Но, в любом случае, паскальные файловые функции - ФТОПКУ, юзай TFileStream.
Расскажу я вам, дружочки, как выращивать грибочки: нужно в поле утром рано сдвинуть два куска урана...
min@y™ вне форума Ответить с цитированием
Старый 31.05.2016, 12:10   #5
URQq
Пользователь
 
Регистрация: 31.05.2016
Сообщений: 11
По умолчанию

Цитата:
Сообщение от Serge_Bliznykov Посмотреть сообщение
Это мусор, который находится в памяти. Он там никому не мешает, т.к. в строке есть либо длина строки (это в начале строки или в управляющей структуре, Pascal-подобные строки), либо строка заканчивается нулём (C-подобные строки).

Теперь, что делать Вам. Если мусор Вам мешает, то Вы можете банально заполнять нулями строку:
Код:
while Length(s)<8 do s := s + #0;
Спасибо! Решение оказалось очень простым. После десятилетнего перерыва делаю банальные ошибки.

Цитата:
Сообщение от Serge_Bliznykov Посмотреть сообщение
вообще, я бы лично писал в файл сначала длину строки (Intgere), а потом полностью всё строку. Это позволило бы: 1) не заботиться о мусоре, которого там бы не было по определению 2) возможность писать пустые строки и строки длиной в сотни и тысячи символов
Я бы тоже так сделал, но задача стоит иная. Есть определенный файл, который должен быть вшит в прибор и он чётко расписан по адресам. Добавить байты о длине строк не имею возможности, выйду за рамки размера файла.

Цитата:
Сообщение от Serge_Bliznykov Посмотреть сообщение
p.s. и вообще, зачем Вам олдскульный BlockWrite - чем Вас TFileStream не устраивает?!
Как я уже писал, перерыв в программировании около 10-ти лет. Спасибо ещё раз за подсказку, буду изучать TFileStream.

Решение(если кому нужно будет):

Код:
...
  Str := DBGrid1.DataSource.DataSet.FieldByName('Str').Text;
  AssignFile(myFile, SaveDialog2.FileName);
  ReWrite(myFile, 1);
  while Length(Str) < 8 do Str := Str + #0;
  BlockWrite(myFile, Str[1], 8);
...
URQq вне форума Ответить с цитированием
Старый 31.05.2016, 13:16   #6
Serge_Bliznykov
Старожил
 
Регистрация: 09.01.2008
Сообщений: 26,229
По умолчанию

Хорошо.

Ещё совет, на будущее - не стоит использовать имена стандартных функций в качестве идентификаторов - замените Str на что-нибудь более подходящее.
На худой случай, если ничего не придумаете, то, хотя бы на StrText
Serge_Bliznykov вне форума Ответить с цитированием
Старый 31.05.2016, 13:27   #7
URQq
Пользователь
 
Регистрация: 31.05.2016
Сообщений: 11
По умолчанию

Цитата:
Сообщение от Serge_Bliznykov Посмотреть сообщение
Хорошо.

Ещё совет, на будущее - не стоит использовать имена стандартных функций в качестве идентификаторов - замените Str на что-нибудь более подходящее.
На худой случай, если ничего не придумаете, то, хотя бы на StrText
Да, я знаю.
Просто для примера так написал, что бы не писать модуль var s: string. Подумал, что сразу ясно будет Str - string, Int - integer и т.д.
В программе у меня, конечно же, иначе.
URQq вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Поблоковая запись в файл(BlockWrite) Finnesko Помощь студентам 9 10.11.2012 15:24
Небольшое затруднение egorzenit Общие вопросы Delphi 8 08.07.2011 18:41
небольшое затруднение cargo29 Общие вопросы Delphi 6 22.12.2010 15:47
Запись String через BlockWrite Alex Cones Общие вопросы Delphi 3 13.09.2010 20:47
Проблема с Blockwrite inndim Общие вопросы Delphi 7 13.03.2009 08:38