Сохраняйте конечные пробелы при последовательной записи в строку организации файла

Я использую GnuCOBOL и пишу в файл, организация последовательная, и мне нужно сохранять конечные пробелы. Последовательность строк добавляет символы [CR][LF], но делает это после удаления конечных пробелов.

       IDENTIFICATION DIVISION.
       PROGRAM-ID. TRAILING-SPACES.

       ENVIRONMENT DIVISION.
       INPUT-OUTPUT SECTION.
       FILE-CONTROL.
           SELECT OUTFILE 
           ASSIGN 'O:\BATCH_JOBS\TMP\TRAILING-SPACES.COBOL.TXT'
           ORGANIZATION IS LINE SEQUENTIAL.

       DATA DIVISION.
       FILE SECTION.
       FD OUTFILE
           DATA RECORD IS OUT-RECORD.

       01 OUT-RECORD.
          05 STUFF PIC X(5).

       PROCEDURE DIVISION.
           OPEN OUTPUT OUTFILE.

           MOVE 'ABCDE' TO STUFF.
           WRITE OUT-RECORD.

           MOVE 'ABC  ' TO STUFF.
           WRITE OUT-RECORD.

           CLOSE OUTFILE.
           STOP RUN.

Результат:

ABCDE[CR][LF]

АБВ[CR][LF]

Как мне получить результат

ABCDE[CR][LF]

ABC[ПРОБЕЛ][ПРОБЕЛ][CR][LF]

Я попытался объявить файл как последовательную организацию и сгенерировать [CR][LF], но, похоже, мне не удалось заставить его работать.

       IDENTIFICATION DIVISION.
       PROGRAM-ID. TRAILING-SPACES.

       ENVIRONMENT DIVISION.
       INPUT-OUTPUT SECTION.
       FILE-CONTROL.
           SELECT OUTFILE 
           ASSIGN 'O:\BATCH_JOBS\TMP\TRAILING-SPACES.COBOL.TXT'
           ORGANIZATION IS SEQUENTIAL.

       DATA DIVISION.
       FILE SECTION.
       FD OUTFILE
           DATA RECORD IS OUT-RECORD.

       01 OUT-RECORD.
          05 STUFF PIC X(5).
          05 CR PIC X(1) VALUE X'0D'.
          05 LF PIC X(1) VALUE X'0A'.

       PROCEDURE DIVISION.
           OPEN OUTPUT OUTFILE.

           MOVE 'ABCDE' TO STUFF.
           WRITE OUT-RECORD.

           MOVE 'ABC  ' TO STUFF.
           WRITE OUT-RECORD.

           CLOSE OUTFILE.
           STOP RUN.

Результат:

ABCDE[NUL][NUL]ABC[ПРОБЕЛ][ПРОБЕЛ][NUL][NUL]

Всем спасибо!

Просто предполагаю, поскольку я не использовал COBOL почти 35 лет, но согласно документации: при чтении файла «LINE SEQUENTIAL» записи, превышающие размер, указанный в описании файла в «РАЗДЕЛЕ ФАЙЛА», будут обрезаны, а записи короче этого размера будет дополнено справа «ПРОБЕЛАМИ» - поэтому в вашем случае, когда запись будет прочитана обратно, она будет содержать конечные пробелы.

bdcoder 09.04.2024 16:41

Я тоже не прикасался к COBOL уже 30 лет. Вы абсолютно правы, и я ожидаю, что COBOL сделает именно это: если буфер слишком мал, то усеките его, а если буфер слишком велик, то дополните его. Что меня ломает голову, так это то, почему запись в файл приводит к удалению конечных пробелов. В других языках давайте просто выберем C#, outfile.writeline("Привет, bdcoder <куча пробелов> "); будет включать пробелы. У него не будет побочных эффектов или каких-то необычных действий... он просто будет делать то, что вы ему скажете. Но спасибо за комментарий и за то, что поделились!

SubwayDawg 09.04.2024 18:17
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
2
63
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

ORGANIZATION LINE SEQUENTIAL был стандартизирован в COBOL2023, но в то же время в нескольких реализациях все было по-другому.

Для этого в общих правилах для WRITE указано:

Для последовательного построчного файла с записью описания файла, не содержащей предложения RECORD с фразой DEPENDING, любые пробелы справа от крайнего правого символа, не являющегося пробелом, не переносятся в имя_файла-1.

GnuCOBOL по умолчанию следует стандарту, но позволяет вам настроить поведение, см. руководство в разделе «Приложение I Конфигурация среды выполнения, ввод-вывод файла» (или конфигурацию среды выполнения runtime.cfg, см. cobcrun --runtime-config, чтобы проверить, где она находится):

Environment name:  COB_LS_FIXED
  Parameter name:  ls_fixed
         Purpose:  Defines if LINE SEQUENTIAL files should be fixed length
                   (or variable, by removing trailing spaces)
           Alias:  STRIP_TRAILING_SPACES  (0 = yes)
            Type:  boolean
         Default:  false
            Note:  This setting is most useful if you want to REWRITE those
                   files.
         Example:  LS_FIXED TRUE

Environment name:  COB_LS_VALIDATE
  Parameter name:  ls_validate
         Purpose:  Defines for LINE SEQUENTIAL files that the data should be
                   validated as it is read (status 09) / written (status 71).
            Type:  boolean
         Default:  true (per COBOL 2022)
            Note:  If active effectively disables COB_LS_NULLS.
         Example:  LS_VALIDATE FALSE

Environment name:  COB_LS_NULLS
  Parameter name:  ls_nulls
         Purpose:  Defines for LINE SEQUENTIAL files what to do with data
                   which is not DISPLAY type.  This could happen if a LINE
                   SEQUENTIAL record has BINARY/COMP data fields in it.
            Type:  boolean
         Default:  false
            Note:  The TRUE setting will insert a null character x"00" before
                   those values to escape them, and redo on read-in plus
                   validating that they only occur after a null character.
                   Decreases LINE SEQUENTIAL performance and prevents writing
                   escape sequences or formatting within the data.
                   Only checked if COB_LS_VALIDATE is disabled.
         Example:  LS_NULL = TRUE

Environment name:  COB_LS_SPLIT
  Parameter name:  ls_split
         Purpose:  Defines for LINE SEQUENTIAL files what to do when a record
                   is longer than the program handles. If 'ls_split=true' then
                   the data is returned as multiple records with io status 06,
                   otherwise the record is truncated, io status set to 04 and
                   the file skips to the next LF.
            Type:  boolean
         Default:  true (per COBOL 2022)
         Example:  LS_SPLIT = FALSE

Если вы хотите изменить это глобально, отредактируйте свой runtime.cfg (или, что лучше, создайте собственный), включив в него

ls_fixed = true
ls_split = false

в качестве альтернативы: просто поместите это в окружающую среду

SET COB_LS_FIXED=1
SET COB_LS_SPLIT=0

или сделайте это из программы COBOL перед обработкой файла:

SET ENVIRONMENT "COB_LS_FIXED" TO "1"
SET ENVIRONMENT "COB_LS_SPLIT" TO "0"

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

Поэтому, вероятно, лучше вместо этого скорректировать запись описания файла (и, возможно, избавиться от стандарта «больше нет» DATA RECORD, который уже дублируется записью под FD):

       FD OUTFILE
           RECORD IS VARYING IN SIZE FROM 1 TO 5 BYTES
           DEPENDING ON OUTFILE-LEN.

с

    77  OUTFILE-LEN PIC 99 COMP-5 VALUE LENGTH OF OUT-RECORD.

в WORKING-STORAGE SECTION (в вашем примере предварительно установлено значение 5, но вы также можете указать это перед WRITE). Примечание. Длина будет автоматически установлена ​​на READ в соответствии с тем, что найдено в файле.

Это также должно быть более переносимо в другие среды COBOL.

Ух ты! Спасибо, Саймон, за образование. Это сработало! Я внес предложенные вами изменения в FD и добавил 77 уровень. После реализации ваших предложений, но без установки переменных среды, усечение продолжалось, но с переменными (а также FD и 77) все работало нормально. Я использую GnuCOBOL 3.2.0, и ему не нравятся BYTES в FD. Он жалуется на «ошибку: «BYTES» является зарезервированным словом, но не поддерживается»; Я заменил его ПЕРСОНАЖАМИ. Я еще раз смиренно благодарю вас за понимание и за то, что поделились с нами своим опытом.

SubwayDawg 10.04.2024 15:10
Ответ принят как подходящий
       01 OUT-RECORD.
          05 STUFF PIC X(5).
          05 CR PIC X(1) VALUE X'0D'.
          05 LF PIC X(1) VALUE X'0A'.

Эти пункты VALUE игнорируются в FILE SECTION.

Есть несколько способов это изменить, но самый простой — разместить код в WORKING-STORAGE SECTION.

       01 OUT-RECORD PIC X(7).

       WORKING-STORAGE SECTION.
       01 WS-OUT-RECORD.
          05 STUFF PIC X(5).
          05 CR PIC X(1) VALUE X'0D'.
          05 LF PIC X(1) VALUE X'0A'.

Затем

           MOVE "ABC" TO STUFF
           WRITE OUT-RECORD FROM WS-OUT-RECORD

Это не совсем так. Предложения VALUE просто не меняют начальное содержимое памяти (и по стандарту память определяется как доступная только после успешного OPEN). Они полностью используются для INITIALIZE OUT-RECORD ALL TO VALUE, который можно использовать после OPEN. ... но главный тезис "их нет (автоматически) в памяти, понятнее использовать WS и WRITE FROM" однозначно верен.

Simon Sobisch 10.04.2024 11:53

О, вот почему! Я не знал «переменных» в FD, а переменные в рабочей памяти обрабатываются по-другому. Я просто подумал, что переменные — это переменные, которые есть переменные (с учетом правил области видимости). Например, в C вы можете объявить переменную практически где угодно. Рик и Саймон: спасибо вам обоим за содержательные и чрезвычайно полезные ответы!

SubwayDawg 16.04.2024 02:37

Другие вопросы по теме