Table of Contents
- 1. File Operations
- 1.1. Overview
- 1.2. File Basics
- 1.3. Reading from Files
- 1.4. Writing to Files
- 1.5. Standard I/O
- 1.6. File Filters
- 1.7. Temporary Files
- 1.8. File Positioning
- 1.9. Loading External Code
- 1.10. Data Files
- 1.11. File Management
- 1.12. Binary File Operations
- 1.13. Practical Examples
- 1.14. Error Handling
- 1.15. Performance Tips
- 1.16. Best Practices
- 1.17. Common Pitfalls
- 1.18. See Also
1. File Operations
PostScript provides comprehensive file I/O capabilities for reading and writing data, managing resources, and creating modular programs. Understanding file operations is essential for advanced PostScript programming.
1.1. Overview
File operations in PostScript include:
-
File access - Opening, reading, and writing files
-
Standard I/O - stdin, stdout, stderr
-
Filters - Data encoding/decoding
-
String operations - String-based I/O
-
Resource loading - External data and code
-
Temporary storage - Working with file buffers
PostScript treats files as streams of bytes that can be read, written, or both.
1.2. File Basics
1.2.1. Opening Files
% file: filename access file
% access: (r)ead, (w)rite, (r+) read/write
% Open for reading
(input.ps) (r) file /inputFile exch def
% Open for writing
(output.dat) (w) file /outputFile exch def
% Open for read/write
(data.tmp) (r+) file /dataFile exch def
1.3. Reading from Files
1.3.1. Reading Strings
% read: file read -> int true | false
% Reads one byte
(input.txt) (r) file /f exch def
f read {
= % Print the byte
} {
(End of file) print
} ifelse
f closefile
1.3.2. Reading Lines
% readline: file string readline -> substring true | false
(input.txt) (r) file /f exch def
256 string /buffer exch def
% Read one line
f buffer readline {
% Got a line
print
} {
(End of file) print
} ifelse
f closefile
Reading all lines:
/readAllLines { % filename -> -
(r) file
256 string
{
2 copy readline not { exit } if
print (\n) print
} loop
pop closefile
} def
% Usage
(myfile.txt) readAllLines
1.3.3. Reading Tokens
% token: string token -> post any true | false
% token: file token -> any true | false
(data.ps) (r) file /f exch def
% Read PostScript tokens
f token {
% Got token
= % Print it
% Read another
f token {
=
} if
} if
f closefile
1.3.4. Reading Binary Data
% readstring: file string readstring -> substring boolean
(binary.dat) (r) file /f exch def
1024 string /buffer exch def
f buffer readstring {
% Read full buffer
(Read ) print dup length =
} {
% Read partial (EOF)
(Read ) print dup length = (bytes before EOF) print
} ifelse
f closefile
1.4. Writing to Files
1.4.1. Writing Strings
% write: file int write
(output.txt) (w) file /f exch def
% Write bytes
f 72 write % 'H'
f 105 write % 'i'
f 10 write % newline
f closefile
1.4.2. Writing Lines
% writestring: file string writestring
(output.txt) (w) file /f exch def
f (Hello, World!) writestring
f (\n) writestring
f (Second line) writestring
f (\n) writestring
f closefile
1.4.3. Writing Formatted Data
/writeFormatted { % file values... count template -> -
3 dict begin
/template exch def
/count exch def
/f exch def
% Write formatted output
count {
template
exch =string cvs
concatstrings
f exch writestring
} repeat
end
} def
% Usage
(output.txt) (w) file /f exch def
f 42 99 2 (Value: %\n) writeFormatted
f closefile
1.5. Standard I/O
1.5.1. Standard Input
% Read from stdin
(%stdin) (r) file /stdin exch def
stdin 256 string readline {
(You entered: ) print
print
} if
stdin closefile
1.6. File Filters
1.6.1. ASCII85 Encoding
% Encode data to ASCII85
(output.a85) (w) file
/ASCII85Encode filter /encoded exch def
encoded (Raw data to encode) writestring
encoded closefile
% Decode ASCII85
(input.a85) (r) file
/ASCII85Decode filter /decoded exch def
256 string /buffer exch def
decoded buffer readstring pop
decoded closefile
1.6.2. Hexadecimal Encoding
% ASCIIHexEncode filter
(output.hex) (w) file
/ASCIIHexEncode filter /hexFile exch def
hexFile (Data) writestring
hexFile closefile
% ASCIIHexDecode filter
(input.hex) (r) file
/ASCIIHexDecode filter /hexIn exch def
256 string hexIn exch readstring pop
hexIn closefile
1.6.3. Run-Length Encoding
% RunLengthEncode filter
(output.rle) (w) file
/RunLengthEncode filter /rleFile exch def
rleFile (Repeated data...) writestring
rleFile closefile
% RunLengthDecode filter
(input.rle) (r) file
/RunLengthDecode filter /rleIn exch def
1024 string rleIn exch readstring pop
rleIn closefile
1.7. Temporary Files
1.8. File Positioning
1.8.1. File Position
% fileposition: file -> position
(data.txt) (r) file /f exch def
% Get current position
f fileposition = % Prints current offset
% Read some data
f 256 string readline pop
% Check new position
f fileposition =
f closefile
1.9. Loading External Code
1.9.1. Running External Scripts
% run: filename run
% Executes PostScript file
(library.ps) run
% Or with error handling
(script.ps) {
run
} stopped {
(Error loading script) print
} if
1.10. Data Files
1.10.1. CSV File Reading
/readCSV { % filename -> array
10 dict begin
/lines [] def
(r) file
256 string
{
2 copy readline not { exit } if
% Parse CSV line
(,) {
search {
% Found comma
/lines [ lines aload pop 4 -1 roll ] def
} {
% Last field
/lines [ lines aload pop ] def
exit
} ifelse
} loop
} loop
pop closefile
lines
end
} def
% Usage
(data.csv) readCSV
1.10.2. Configuration Files
/loadConfig { % filename -> dict
10 dict begin
/config 20 dict def
(r) file /f exch def
256 string /line exch def
{
f line readline not { exit } if
% Parse key=value
(=) search {
% Found =
/value exch def
pop % Discard =
/key exch def
% Store in config
config key value put
} {
% No =, skip line
pop
} ifelse
} loop
f closefile
config
end
} def
% Usage
(config.txt) loadConfig /settings exch def
settings /server get print
1.10.3. JSON-like Data
/parseSimpleJSON { % string -> dict
% Simplified JSON parser
% Format: {key: value, key: value}
20 dict begin
/result 10 dict def
% Remove braces
dup 0 get 123 eq { 1 exch length 2 sub getinterval } if
% Split by comma
{
(,) search {
% Parse key:value pair
(:) search {
/value exch def
pop
/key exch def
% Clean and store
result
key strip
value strip
put
} if
} {
% Last pair
(:) search {
/value exch def
pop
/key exch def
result key strip value strip put
} if
exit
} ifelse
} loop
result
end
} def
/strip { % string -> trimmedString
% Remove leading/trailing spaces
dup length 0 gt {
dup 0 get 32 eq {
1 exch length 1 sub getinterval strip
} if
} if
} def
1.11. File Management
1.11.1. File Existence Check
/fileExists { % filename -> boolean
{
(r) file closefile
true
} stopped {
pop false
} ifelse
} def
% Usage
(myfile.txt) fileExists {
(File exists) print
} {
(File not found) print
} ifelse
1.11.2. File Copy
/copyFile { % srcFile dstFile -> -
2 dict begin
/dst exch def
/src exch def
src (r) file /inFile exch def
dst (w) file /outFile exch def
1024 string /buffer exch def
{
inFile buffer readstring {
outFile exch writestring
} {
outFile exch writestring
exit
} ifelse
} loop
inFile closefile
outFile closefile
end
} def
% Usage
(source.txt) (destination.txt) copyFile
1.12. Binary File Operations
1.12.1. Writing Binary Data
/writeBinary { % filename data -> -
2 dict begin
/data exch def
/fname exch def
fname (w) file /f exch def
data {
f exch write
} forall
f closefile
end
} def
% Usage
(binary.dat) [0 255 128 64 32] writeBinary
1.12.2. Reading Binary Data
/readBinary { % filename size -> array
2 dict begin
/size exch def
/fname exch def
fname (r) file /f exch def
size string /buffer exch def
f buffer readstring pop
f closefile
[
0 1 buffer length 1 sub {
buffer exch get
} for
]
end
} def
% Usage
(binary.dat) 100 readBinary
1.13. Practical Examples
1.13.1. Example 1: Log File Writer
/Logger {
10 dict begin
/logFile null def
/filename exch def
/open {
filename (a) file /logFile exch def
} def
/close {
logFile null ne {
logFile closefile
/logFile null def
} if
} def
/log { % message level -> -
2 dict begin
/level exch def
/msg exch def
logFile null eq { open } if
% Format: [timestamp] LEVEL: message
logFile ([) writestring
logFile realtime =string cvs writestring
logFile (] ) writestring
logFile level writestring
logFile (: ) writestring
logFile msg writestring
logFile (\n) writestring
end
} def
currentdict
end
} def
% Usage
(app.log) Logger /logger exch def
logger /log (Application started) (INFO) exec
logger /log (Processing data) (DEBUG) exec
logger /log (Error occurred) (ERROR) exec
logger /close exec
1.13.2. Example 2: Data Exporter
/DataExporter {
10 dict begin
/data exch def
/filename exch def
/exportCSV {
filename (w) file /f exch def
% Write header
f (X,Y,Value\n) writestring
% Write data
data {
aload pop
f exch =string cvs writestring
f (,) writestring
f exch =string cvs writestring
f (,) writestring
f exch =string cvs writestring
f (\n) writestring
} forall
f closefile
} def
currentdict
end
} def
% Usage
[
[10 20 100]
[30 40 200]
[50 60 300]
] (data.csv) DataExporter /exporter exch def
exporter /exportCSV exec
1.13.3. Example 3: Template Processor
{% raw %}
/processTemplate { % templateFile dataDict outputFile -> -
3 dict begin
/outFile exch def
/data exch def
/tmplFile exch def
tmplFile (r) file /inF exch def
outFile (w) file /outF exch def
256 string /line exch def
{
inF line readline not { exit } if
% Replace {{key}} with value
{
({{) search not { exit } if
% Write before match
outF exch writestring
pop % Discard {{
(}}) search {
% Found closing }}
/key exch def
pop % Discard }}
% Write replacement
data key known {
outF data key get writestring
} {
outF ({{) writestring
outF key writestring
outF (}}) writestring
} ifelse
} {
% No closing }}
outF ({{) writestring
} ifelse
} loop
% Write rest of line
outF exch writestring
outF (\n) writestring
} loop
inF closefile
outF closefile
end
} def
% Usage
<<
/name (John Doe)
/email (john@example.com)
>> (template.txt) (output.txt) processTemplate
{% endraw %}
1.13.4. Example 4: Batch File Processor
/processBatch { % directory pattern processor -> -
3 dict begin
/proc exch def
/pattern exch def
/dir exch def
% List files matching pattern
% (simplified - actual file listing is system-dependent)
[
(file1.txt)
(file2.txt)
(file3.txt)
] {
/filename exch def
% Process each file
dir filename concatstrings proc exec
} forall
end
} def
% Usage
(data/) (*.txt) {
dup print ( processed) print (\n) print
% Process file here
} processBatch
1.14. Error Handling
1.14.1. Safe File Operations
/safeFileOpen { % filename mode -> file true | false
2 copy
{
file
true
} stopped {
pop pop pop
false
} ifelse
} def
% Usage
(myfile.txt) (r) safeFileOpen {
/f exch def
% Use file
f closefile
} {
(Could not open file) print
} ifelse
1.14.2. File Operation with Cleanup
/withFile { % filename mode proc -> -
3 dict begin
/proc exch def
/mode exch def
/fname exch def
fname mode file /f exch def
{
f proc exec
} stopped {
% Ensure file is closed on error
f closefile
(File operation failed) print
} {
f closefile
} ifelse
end
} def
% Usage
(data.txt) (r) {
256 string readline {
print
} if
} withFile
1.15. Performance Tips
1.15.1. Buffer Size
% Good: appropriate buffer
4096 string /buffer exch def
file buffer readstring
% Bad: tiny buffer (many reads)
10 string /buffer exch def
file buffer readstring
1.16. Best Practices
1.16.1. Always Close Files
% Good: guaranteed close
(file.txt) (r) file
dup
% ... use file
closefile
% Better: with error handling
{
(file.txt) (r) file
dup
% ... use file
closefile
} stopped {
pop
(Error) print
} if
1.17. Common Pitfalls
1.17.1. Not Closing Files
% Wrong: file leak
(file.txt) (r) file
% ... forget to close
% Correct
(file.txt) (r) file
dup
% ... use file
closefile
1.18. See Also
-
Error Handling - File operation errors
-
Resource Management - Managing file resources
-
Procedures - File processing procedures
-
Command Reference - File operators