= How programming languages read and write data

:Author: Seth Kenlon
:Email: [email protected]

In his article https://opensource.com/article/21/4/compare-programming-languages[How different programming languages do the same thing], Jim Hall demonstrated how 13 different languages accomplish the same exact task with different syntax.
The lesson was that programming languages tend to have many similarities, and once you know one programming language you can learn another by figuring its syntax and structure.
In the same spirit, this article compares how different programming languages read and write data.
Whether that data comes from a configuration file or from a file that a user has created, processing data on a storage device is a common task for coders.
It's not practical to cover all programming languages, but a recent series on opensource.com provides insight into different approaches taken by different coding languages.

* https://opensource.com/article/21/3/file-io-c
* https://opensource.com/article/21/3/ccc-input-output
* https://opensource.com/article/21/3/io-java
* https://opensource.com/article/21/4/groovy-io
* https://opensource.com/article/21/3/lua-files
* https://opensource.com/article/21/3/input-output-bash
* LINK-TO-THE-PYTHON-IO-ARTICLE

== Reading and writing data

The process of reading and writing data with a computer is similar to how you read and write data in real life.
To access data in a book, you first open a book, then you read words or you write new words into the book, and then you close the book.

When your code needs to read data from a file, you provide your code with a file location, and then that data is brought into the computer's RAM and parsed from there.
Similarly, when your code needs to write data to a file, new data is placed into the system's in-memory write buffer, and then syncronized to the file on the storage device.

Here's some pseudo-code for these operations:

1. Load a file in memory
2. Read the file's contents, or write data to the file
3. Close the file

== Reading data from a file

In the languages we wrote about here on opensource.com, there are three trends.

=== C

In C, opening a file can involve retrieving a single character (up to the `EOF` designator, signaling the end of the file) or a block of data, depending on your requirements and approach.
It can feel like a mostly manual process, depending on your goal, but the general process is exactly what all the rest of the languages mimic.

[source,c]
----
FILE *infile;
int ch;

infile = fopen(argv[1], "r");

do {
 ch = fgetc(infile);
 if (ch != EOF) {
   printf("%c", ch);
 }
} while (ch != EOF);

fclose(infile);
----

You can alternately choose to load some portion of a file into the system buffer, and then work out of the buffer.

[source,c]
----
FILE *infile;
char buffer[300];

infile = fopen(argv[1], "r");

while (!feof(infile)) {
 size_t buffer_length;
 buffer_length = fread(buffer, sizeof(char), 300, infile);
}

printf("%s", buffer);
fclose(infile);
----

=== C++

C++ is able to simplify a few steps for you, allowing you to parse data as strings.

[source,c++]
----
std::string sFilename = "example.txt";

std::ifstream fileSource(sFilename);
std::string buffer;

while (fileSource >> buffer) {
 std::cout << buffer << std::endl;
}
----

=== Java

Java and Groovy are similar to C++, using a class called `Scanner` to set up a data object or stream containing the contents of the file of your choice.
You can "scan" through the file by tokens (byte, line, integer, and many others).

[source,java]
----
File myFile = new File("example.txt");

Scanner myScanner = new Scanner(myFile);
 while (myScanner.hasNextLine()) {
   String line = myScanner.nextLine();
   System.out.println(line);
 }

myScanner.close();
----

=== Groovy

[source,java]
----
def myFile = new File('example.txt')

def myScanner = new Scanner(myFile)
 while (myScanner.hasNextLine()) {
   def line = myScanner.nextLine()
   println(line)
 }

myScanner.close()
----

=== Lua

Lua and Python abstract the process further.
You don't have to consciously create a data stream, you just assign a variable to the results of an `open` function, and then parse the contents of the variable.
It's quick, minimal, and easy.

[source,c]
----
myFile = io.open('example.txt', 'r')

lines = myFile:read("*all")
print(lines)

myFile:close()
----

=== Python

[source,python]
----
f = open('example.tmp', 'r')

for line in f:
   print(line)

f.close()
----

== Writing data to a file

In terms of code, writing is the inverse of reading.
As such, the process for writing data to a file is basically the same as reading data from a file, except using different functions.

=== C

In C, you can write a character to a file with the `fputc` function:

[source,c]
----
fputc(ch, outfile);
----

Alternately, you can write data to the buffer with `fwrite`:

[source,c]
----
fwrite(buffer, sizeof(char), buffer_length, outfile);
----

=== C++

Because C++ uses the `ifstream` library to open a buffer for data, you can write data to the buffer, as with C (except with C++ libraries):

[source,c++]
----
std::cout << buffer << std::endl;
----

=== Java

In Java, you can use the `FileWriter` class to create a data object that you can write data to.
It works a lot like the `Scanner` class, except going the other way.

[source,Java]
----
FileWriter myFileWriter = new FileWriter("example.txt", true);
myFileWriter.write("Hello world\n");
myFileWriter.close();
----

=== Groovy

Similarly, Groovy uses `FileWriter` but with a slightly "groovier" syntax:

[source,Java]
----
new FileWriter("example.txt", true).with {
 write("Hello world\n")
 flush()
}
----

=== Lua

Lua and Python are similar, both using functions called `open` to load a file, `write` to put data into it, and `close` to close the file.

[source,c]
----
myFile = io.open('example.txt', 'a')
io.output(myFile)
io.write("hello world\n")
io.close(myFile)
----

=== Python

[source,Python]
----
myFile = open('example.txt', 'w')
myFile.write('hello world')
myFile.close()
----

== File modes

Many languages specify a "mode" when opening files.
Modes vary, but this is common notation:

* *w* to write
* *r* to read
* *r+* to read and write
* *a* to append only

Some languages, such as Java and Groovy, let you determine the mode based on which class you use to load the file.

However your programming language of choice determines a file's mode, it's up to you to ensure that you're _appending_ data unless you intend to overwrite a file with new data!
Programming languages don't have built-in prompts to warn you against data loss, the way file choosers do.

== New language and old tricks

Every programming language has a unique way of accomplishing a task, that's why there are so many languages to choose from.
You can and should choose the language that works best for you.
But once you understand the basic constructs of programming, you can also feel free to try out different languages, without the fear of not knowing how to accomplish basic tasks.
More often than not, the pathways to a goal are similar, and so they're easy to learn as long as you keep the basics concepts in mind.