Your country

Tools that support it use your country for local currency, number formats, units and paper size. Your choice is saved only in this browser.

Type a name or a two-letter code. Use the up and down arrow keys to move through the countries, Enter to choose one and Escape to close.

COBOL  Module 9 – EBCDIC, record layouts, Unicode and JSON

UTF-8, national data and names in Indian scripts

See why byte-based PIC X fields break UTF-8 names in Devanagari and other Indian scripts, how to size and check them, and what national data offers.

  • Intermediate
  • 20 minutes
  • Examples run with GnuCOBOL 3.2, Python 3.14.8 and Pyodide 314.0.7
  • By MySmartCoPilot
Free core, Pro depth: 8 of 20 minutes free
Free: A PIC X field counts bytes, and UTF-8 needs up to four for a character · Names in Indian scripts take three bytes a character, and national data counts characters · Practise: bytes, characters and fields. With a pass: 2 in-depth parts and 3 interview answers, about 12 minutes.

What you will learn

  • Explain why byte-based PIC X fields break UTF-8 text such as names in Devanagari
  • Size fields for names in Indian scripts and check that a field holds valid UTF-8
  • Write a routine that cuts a UTF-8 name to a byte limit without splitting a character
  • Compare national (UTF-16) and UTF-8 support in IBM Enterprise COBOL 6.5 and GnuCOBOL 3.2

Before you start

What you’ll learn · Before you start

What you will learn

  • Explain why byte-based PIC X fields break UTF-8 text such as names in Devanagari
  • Size fields for names in Indian scripts and check that a field holds valid UTF-8
  • Write a routine that cuts a UTF-8 name to a byte limit without splitting a character
  • Compare national (UTF-16) and UTF-8 support in IBM Enterprise COBOL 6.5 and GnuCOBOL 3.2

Before you start

On this page

The name अनीता देशमुख is 12 characters and 34 bytes in UTF-8, so a PIC X(30) field that looks roomy cuts it, and a PIC X(10) field cuts the letter त in half. COBOL’s PIC X counts bytes, and names in Indian scripts take about three bytes a character.

This lesson measures names in six scripts, shows what MOVE, UPPER-CASE and REVERSE do to UTF-8 text in GnuCOBOL, and names what national data and IBM’s UTF-8 items count instead.

A PIC X field counts bytes, and UTF-8 needs up to four for a character

In UTF-8: A Unicode encoding that stores each code point in one to four bytes: one for ASCII characters, three for most characters of the Indian scripts. A byte from X'80' to X'BF' only continues a character. a character takes one to four bytes; IBM’s Programming Guide says its encoding “is always between one and four bytes”. The Latin letters of ASCII take one, and a Devanagari letter takes three. A PIC X field, and every statement that works on it, counts bytes. names.cob puts the name in byte-based fields and calls three text functions on it, and valuecut.cob gives the name, as a VALUE, to a field of 30 bytes:

names.cob: a Devanagari name in PIC X fields COB · names.cob
       IDENTIFICATION DIVISION.
       PROGRAM-ID. NAMES.
      * A name in Devanagari in byte-based PIC X fields.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  NAME-40                 PIC X(40).
       01  NAME-10                 PIC X(10).
       01  WS-BYTES                PIC 99.
       01  NAME-REV                PIC X(10).
       PROCEDURE DIVISION.
           MOVE "अनीता देशमुख" TO NAME-40
           MOVE FUNCTION LENGTH (FUNCTION TRIM (NAME-40)) TO WS-BYTES
           DISPLAY "bytes used:   " WS-BYTES
           DISPLAY "as written:   [" FUNCTION TRIM (NAME-40) "]"
           MOVE NAME-40 TO NAME-10
           DISPLAY "into X(10):   [" NAME-10 "]"
           DISPLAY "its bytes:    " FUNCTION HEX-OF (NAME-10)
           DISPLAY "UPPER-CASE:   ["
               FUNCTION UPPER-CASE (FUNCTION TRIM (NAME-40)) "]"
           MOVE FUNCTION REVERSE (NAME-10) TO NAME-REV
           DISPLAY "REVERSE:      " FUNCTION HEX-OF (NAME-REV)
           STOP RUN.
34 bytes, a split letter, and functions that count bytes Python · names_session.py
from session import files, run

# A name in Devanagari in byte-based PIC X fields, then as the VALUE of a field four bytes too short.
# -A passes an option to the C compiler: it quiets clang's warning about the UTF-8 bytes of the literals.
files("names.cob", "valuecut.cob")
run("""
cobc -x -A -Wno-invalid-source-encoding names.cob && ./names
cobc -x -A -Wno-invalid-source-encoding valuecut.cob && ./valuecut | xxd
""")

Output

$ cobc -x -A -Wno-invalid-source-encoding names.cob && ./names
bytes used:   34
as written:   [अनीता देशमुख]
into X(10):   [अनी�]
its bytes:    E0A485E0A4A8E0A580E0
UPPER-CASE:   [अनीता देशमुख]
REVERSE:      E080A5E0A8A4E085A4E0
$ cobc -x -A -Wno-invalid-source-encoding valuecut.cob && ./valuecut | xxd
valuecut.cob:7: warning: value size exceeds data size [-Wothers]
    5 |        WORKING-STORAGE SECTION.
    6 |        01  NAME-30                 PIC X(30)
    7 >            VALUE "अनीता देशमुख".
    8 |        PROCEDURE DIVISION.
    9 |            DISPLAY NAME-30
valuecut.cob:7: note: value size is 34 [-Wothers]
00000000: e0a4 85e0 a4a8 e0a5 80e0 a4a4 e0a4 be20  ...............
00000010: e0a4 a6e0 a587 e0a4 b6e0 a4ae e0a5 0a    ...............

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 names_session.py

The name took 34 bytes. The MOVE into PIC X(10) stopped after byte 10, which is the first of the three bytes of त, so the field ends with a lone E0 that DISPLAY shows as a replacement mark. UPPER-CASE left the name unchanged, since Devanagari has no capitals, and REVERSE reversed bytes, not characters, so its result is not UTF-8 at all. The VALUE clause compiled with only a warning, “value size exceeds data size”, and a note that the value is 34 bytes, and its xxd listing ends with the bytes e0 a5 before DISPLAY’s newline: the vowel sign ु was cut in two at byte 30. Step through the MOVE:

Interactive · step by step A MOVE to PIC X(10) counts bytes, not characters Step through the first characters of the name. Each takes three bytes in UTF-8, and the field ends after byte 10.
A MOVE to PIC X(10) counts bytes, not characters, step 6 of 6. Showing अ, bytes 1 to 3, न, bytes 4 to 6, ी, bytes 7 to 9, त, bytes 10 to 12, NAME-10 (E0A485 E0A4A8 E0A580 E0), What DISPLAY shows (अनी and a broken byte). In focus: What DISPLAY shows, show.MOVE copies bytesअ, bytes 1 to 3E0 A4 85न, bytes 4 to 6E0 A4 A8ी, bytes 7 to 9E0 A5 80त, bytes 10 to 12E0 A4 A4NAME-10E0A485 E0A4A8 E0A580 E0What DISPLAY showsअनी and a broken byte

The drawing shows the whole scene; its 6 steps are listed below.

Every step as text
  1. Twelve characters, 34 bytes. अनीता देशमुख has 12 characters. In UTF-8 each Devanagari character takes three bytes and the space one, so the name is 34 bytes, the number names.cob printed.
  2. The first character. अ is E0 A4 85. E0 starts a character of three bytes, and A4 and 85 only continue it.
  3. A vowel sign is a character too. न is bytes 4 to 6, and the vowel sign ी, which a reader sees as part of नी, is bytes 7 to 9. Both are characters of their own in Unicode.
  4. The tenth byte. The fourth character, त, starts at byte 10. A PIC X(10) field has room for its first byte, E0, and none for the other two.
  5. The MOVE. MOVE fills NAME-10 byte by byte and stops after byte 10. Nothing in PIC X knows that byte 10 began a character.
  6. A broken last character. DISPLAY shows अनी and then a replacement mark, because the lone E0 starts a character that never ends. A file or a database would receive the broken byte as it is.

A name field sized in characters

Wrong: PIC X(30) for “up to 30 characters”, which holds 10 characters of Devanagari. Right: size a PIC X field in bytes, three for each character of the Indian scripts, and never let a MOVE or a VALUE cut the text where it likes.

Names in Indian scripts take three bytes a character, and national data counts characters

name_sizes.py measures seven invented names in six scripts, in code point: The number Unicode gives a character, such as U+0905 for the Devanagari letter अ. What a reader sees as one letter may be several code points, such as a consonant with a vowel sign., in UTF-8 bytes, which a PIC X field holds, and in UTF-16: A Unicode encoding that stores most characters, those of the Indian scripts included, in two bytes. IBM's Enterprise COBOL keeps national data in UTF-16, CCSID 1200. bytes, which national data holds:

Seven names in characters, UTF-8 bytes and UTF-16 bytes Python · sizes/name_sizes.py
"""How big a name is in characters (Unicode code points), in UTF-8 bytes, which is what a PIC X field counts, and in
UTF-16 bytes, which is what national data holds. The names are invented; add your own to NAMES and run it again."""

NAMES = [
    "Anita Deshmukh",
    "José Fernandes",
    "अनीता देशमुख",
    "கவிதா ராமன்",
    "সুমিত ঘোষ",
    "ਹਰਪ੍ਰੀਤ ਕੌਰ",
    "లక్ష్మి రెడ్డి",
]

print(f"{'code points':>12} {'UTF-8 bytes':>12} {'UTF-16 bytes':>13}  name")
for name in NAMES:
    print(f"{len(name):12} {len(name.encode('utf-8')):12} {len(name.encode('utf-16-be')):13}  {name}")

widest = max(len(name.encode("utf-8")) for name in NAMES)
print(f"The longest name here needs PIC X({widest}) in UTF-8.")

Output

 code points  UTF-8 bytes  UTF-16 bytes  name
          14           14            28  Anita Deshmukh
          14           15            28  José Fernandes
          12           34            24  अनीता देशमुख
          11           31            22  கவிதா ராமன்
           9           25            18  সুমিত ঘোষ
          11           31            22  ਹਰਪ੍ਰੀਤ ਕੌਰ
          14           40            28  లక్ష్మి రెడ్డి
The longest name here needs PIC X(40) in UTF-8.

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 name_sizes.py

Names in Indian scripts took about three UTF-8 bytes a code point: the Telugu name has 14 code points and needs 40 bytes, while the Latin name of 14 takes 14, and José takes 15 for its é. In UTF-16 every one of these names takes two bytes a code point, so names in Indian scripts are smaller in UTF-16 than in UTF-8, and Latin names the other way round. A vowel sign or a virama is a code point of its own, so a name of five visible letters may be more code points than that.

Add a name of your own to NAMES and run the program again to see how many bytes its field needs.

COBOL has a second way to hold text. national data: COBOL data items with USAGE NATIONAL and PICTURE N, which Enterprise COBOL holds as UTF-16, so that a field counts characters rather than the bytes of UTF-8., USAGE NATIONAL with PICTURE N, is UTF-16 in Enterprise COBOL: “Define national data items with the USAGE NATIONAL clause to hold national (UTF-16) character strings.” Enterprise COBOL 6.5 also has UTF-8 data items, PICTURE U, which count code points rather than bytes. In GnuCOBOL 3.2, NEWS lists only “parsing support” for USAGE UTF-8, so a program there keeps UTF-8 text in PIC X and must do the counting itself.

Field Holds Counts Bytes for the Telugu name
PIC X(n) UTF-8 bytes bytes 40
PIC N(n) NATIONAL UTF-16 characters 28

Checkpoint

Check: PIC X counts bytes, not characters · UTF-8 and UTF-16 sizes of names

  1. Question 1 of 2 names.cob moved अनीता देशमुख into PIC X(10). What does the field hold?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: The 9 bytes of अनी and E0, the first byte of त

    MOVE works in bytes. The field gets bytes 1 to 10 of the name, and the last of them starts a character whose other two bytes were left out, which DISPLAY shows as a replacement mark.

  2. Question 2 of 2 The Tamil name of name_sizes.py has 11 code points. How many bytes does it take in UTF-16, the encoding of national data?

    Type a number.

    Show the answer: Question 2 of 2

    Answer: 22 bytes

    Every character of these scripts takes two bytes in UTF-16, so 11 code points take 22 bytes, against 31 in UTF-8, as the table printed.

Practise: bytes, characters and fields

These questions use the name, the runs and the table of sizes.

Practice that adapts to you

Practise this lesson

4 questions about 6 ideas of this lesson. Each answer is explained at once, and what you get right is kept in this browser.

  1. Question 1 of 4 How many bytes did names.cob count for अनीता देशमुख?

    Type a number.

    Show the answer: Question 1 of 4

    Answer: 34 bytes

    Eleven Devanagari characters of three bytes each and one space of one byte: 11 × 3 + 1 = 34, as the run printed.

  2. Question 2 of 4 FUNCTION REVERSE turned the bytes E0A485E0A4A8… of the name into E080A5E0A8A4…. What does that show?

    Choose one answer.

    Show the answer: Question 2 of 4

    Answer: REVERSE reverses bytes, so the result is not UTF-8; reversing text needs whole characters, and for Devanagari whole letters

    PIC X functions such as REVERSE, LENGTH and reference modification see bytes. UTF-8 text survives only operations that keep whole characters together.

  3. Question 3 of 4 In which encoding does Enterprise COBOL keep national data?

    Choose one answer.

    Show the answer: Question 3 of 4

    Answer: UTF-16

    National data is UTF-16, two bytes for each character of the Indian scripts; UTF-8 items are a separate kind of data item with PICTURE U.

  4. Question 4 of 4 A file will hold names that are mostly in Indian scripts. In which encoding is a name smaller, and by how much for the Telugu name?

    Choose one answer.

    Show the answer: Question 4 of 4

    Answer: UTF-16, 28 bytes against 40 in UTF-8

    UTF-8 is smaller for Latin text and larger for the Indian scripts, where it needs three bytes against UTF-16's two.

Sizing and validating UTF-8 fields: a safe cut, a validity check and a conjunct kept whole Pro: opens with a Pro, Premium or Ultimate pass

A program that must fit names into fixed fields needs three routines: one that cuts without splitting a character, one that proves a field holds valid UTF-8, and a rule that keeps a written letter whole. This part builds the first two in COBOL and shows the third with names that need it.

In this part:

  • Cutting a name to a byte limit without splitting a character
  • Cut a UTF-8 name to a byte limit without splitting a character
    • Results of the sample tests
  • Checking that a field holds valid UTF-8, as UVALID does
  • A whole code point can still break a conjunct

1 diagram · 5 runnable examples (COB, Python) · 1 exercise with sample tests · about 9 minutes

Opening this part with your pass…

This part opens with any MySmartCoPilot pass.

  • Pro pass · 1 week₹79$2.99
  • 30 days₹179$5.99
  • 1 year₹1,699$45

One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.

It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).

National and UTF-8 data in Enterprise COBOL 6.5 and GnuCOBOL 3.2, compared Pro: opens with a Pro, Premium or Ultimate pass

The same name can live in four kinds of field on z/OS, and in only one of them in GnuCOBOL 3.2. This part sets out what Enterprise COBOL 6.5 offers, compiles the same program with GnuCOBOL, and turns the comparison into a choice.

In this part:

  • What Enterprise COBOL 6.5 offers for Unicode data
  • What GnuCOBOL 3.2 does with the same program
  • One encoding at every boundary, tested with names in several scripts

3 runnable examples (COB, Python) · about 6 minutes

Opening this part with your pass…

This part opens with any MySmartCoPilot pass.

  • Pro pass · 1 week₹79$2.99
  • 30 days₹179$5.99
  • 1 year₹1,699$45

One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.

It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).

Interview questions

A warm-up with its answer, then three questions about names that did not fit:

  1. Fresher to mid · Warm-up

    Why can a PIC X(30) field not hold a 30-character name in Devanagari?

    Because PIC X counts bytes, and UTF-8 stores a Devanagari character in three bytes. PIC X(30) holds 30 bytes, so at most 10 Devanagari characters: the 12 characters of अनीता देशमुख already take 34 bytes. A MOVE or a VALUE into a field that is too short cuts the bytes where the field ends, which can split a character and leave a lone lead byte such as E0, and byte-based functions such as REVERSE and LENGTH work on bytes too. Size UTF-8 fields in bytes, about three for each character of the Indian scripts. On Enterprise COBOL, national data, which is UTF-16, takes two bytes for each of these characters, and UTF-8 items with PICTURE U count code points; GnuCOBOL 3.2 only parses USAGE UTF-8, so there the text stays in PIC X.

  2. Mid to senior

    Customer names in Hindi and Tamil arrive from a web form in UTF-8. After a nightly COBOL job copies them into PIC X(40) fields, the next system rejects some records for invalid characters. What happened, and how do you fix and prove it?

    Model answer, Pro. Model answers open with any pass; prices are in the notice on this page. First step and follow-ups

  3. Fresher to mid

    A new interface must carry customer names of up to 40 characters in any Indian script, or in Latin letters. How many bytes do you give the field in a GnuCOBOL program that keeps UTF-8 in PIC X, and what else goes into the interface description?

    Model answer, Pro. First step and follow-ups

  4. Senior to staff

    A bank plans to store names in Indian scripts in a z/OS COBOL application whose unit tests run with GnuCOBOL on developers' computers. Would you use national data, UTF-8 items or PIC X fields, and why?

    Model answer, Pro. First step and follow-ups

Organisations named on this page

IBM’s Enterprise COBOL pages, RFC 3629 and GnuCOBOL’s NEWS are the sources of the Unicode rules on this page, and every name in it is invented. MySmartCoPilot cites IBM, the GnuCOBOL project and the Python Software Foundation and is part of none of them.

Flashcards · 6 cards

Recall it, then check

Say the answer to yourself before you look: recalling it is what makes it stick.

  1. How many bytes does a character take in UTF-8?

    One to four: an ASCII letter takes one, é takes two and a Devanagari letter takes three.

  2. Why does PIC X(30) not hold a name of 30 Devanagari letters?

    PIC X counts bytes, and each Devanagari letter needs three, so 30 bytes hold 10 of them. The lesson's name of 12 characters needed 34 bytes.

  3. What can a MOVE of a UTF-8 name into a short field do to it?

    It stops at the byte limit wherever that falls, so it can split a character, leaving a lone byte that DISPLAY shows as a replacement mark.

  4. What do UPPER-CASE and REVERSE do to a Devanagari name in GnuCOBOL?

    UPPER-CASE leaves it as it is, since the script has no capitals, and REVERSE reverses its bytes, not its characters, so the result is not valid UTF-8.

  5. How many bytes a code point do names in Indian scripts take in UTF-8 and in UTF-16?

    About three in UTF-8 and two in UTF-16, so national data holds them in fewer bytes; Latin names are the other way round.

  6. What is national data, and what does GnuCOBOL 3.2 offer instead?

    USAGE NATIONAL with PICTURE N holds UTF-16 in Enterprise COBOL, and its PICTURE U items hold UTF-8 counted in code points. GnuCOBOL 3.2 only parses USAGE UTF-8, so a program there keeps UTF-8 in PIC X.

Key takeaways

  • PIC X fields and the statements on them count bytes, so a MOVE, a VALUE or REVERSE can cut or scramble UTF-8 text, and a Devanagari name of 12 characters needs 34 bytes.
  • Names in Indian scripts take about three UTF-8 bytes a code point, and two in UTF-16, so national data holds them in fewer bytes than UTF-8, and Latin names the other way round.
  • Enterprise COBOL 6.5 has national data in UTF-16 and UTF-8 items that count code points, while GnuCOBOL 3.2 only parses USAGE UTF-8, so portable programs keep UTF-8 in PIC X and do the counting themselves.

Terms in this lesson

code point
The number Unicode gives a character, such as U+0905 for the Devanagari letter अ. What a reader sees as one letter may be several code points, such as a consonant with a vowel sign.
conjunct
Consonants joined by a virama, such as क्ष in Devanagari, which a reader sees as one shape but which Unicode stores as three code points.
continuation byte
A UTF-8 byte from X'80' to X'BF', which never starts a character but continues the one before it. A cut placed just before one splits a character.
national data
COBOL data items with USAGE NATIONAL and PICTURE N, which Enterprise COBOL holds as UTF-16, so that a field counts characters rather than the bytes of UTF-8.
UTF-16
A Unicode encoding that stores most characters, those of the Indian scripts included, in two bytes. IBM's Enterprise COBOL keeps national data in UTF-16, CCSID 1200.
UTF-8
A Unicode encoding that stores each code point in one to four bytes: one for ASCII characters, three for most characters of the Indian scripts. A byte from X'80' to X'BF' only continues a character.

References

Related tools

Report a problem with this lesson

Quick answers and tool search

Type to search tools or to get a quick answer, for example 18% of 2500. Use the up and down arrow keys to move through the results, Enter to choose, and Escape to close.