Every language
14 linguagens, copy-ready. One at a time with syntax highlighting, or all inline.
JSJavaScript
import { createReadStream } from 'node:fs';
import { createInterface } from 'node:readline';
const rl = createInterface({
input: createReadStream('app.log'),
crlfDelay: Infinity,
});
for await (const line of rl) {
console.log(line);
}readline over a createReadStream never holds the whole file — readFileSync('app.log', 'utf8').split('\n') is the memory bomb it replaces. crlfDelay: Infinity folds \r\n into one break so Windows logs don't leave a stray \r.
TSTypeScript
import { createReadStream } from 'node:fs';
import { createInterface } from 'node:readline';
const rl = createInterface({
input: createReadStream('errors.log'),
crlfDelay: Infinity,
});
let errors = 0;
for await (const line of rl) {
if (line.startsWith('ERROR')) errors++;
}
console.log(`${errors} error line(s)`);Same runtime as the JavaScript version — line is inferred as string, so no nullish handling is needed. The async iterator ends cleanly at EOF, including a final line with no trailing newline.
GoGo
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
f, err := os.Open("app.log")
if err != nil {
panic(err)
}
defer f.Close()
scanner := bufio.NewScanner(f)
for scanner.Scan() {
fmt.Println(scanner.Text())
}
if err := scanner.Err(); err != nil {
panic(err)
}
}Scan() strips \n and \r\n and yields lines up to 64 KiB by default — a longer line returns bufio.ErrTooLong, so call scanner.Buffer(make([]byte, 0, 64*1024), 1<<20) for ragged logs. Always check scanner.Err() after the loop; the for condition alone swallows read errors.
RsRust
use std::fs::File;
use std::io::{BufRead, BufReader};
fn main() -> std::io::Result<()> {
let file = File::open("app.log")?;
for line in BufReader::new(file).lines() {
println!("{}", line?);
}
Ok(())
}BufRead::lines strips \n and a trailing \r and yields io::Result per line — apply ? to each, since a mid-file read error surfaces exactly there. Without BufReader each line costs a syscall; File alone is unbuffered.
PHPPHP
<?php
$handle = fopen('app.log', 'r');
while (($line = fgets($handle)) !== false) {
echo rtrim($line, "\r\n"), PHP_EOL;
}
fclose($handle);fgets keeps the trailing newline and returns false at EOF — compare with !== false, because a last line of "0" loosely equals false and would end the loop a line early. file('app.log') loads every line into an array instead; rtrim removes the \n and the \r of CRLF.
PyPython
from pathlib import Path
with Path("app.log").open(encoding="utf-8") as f:
for line in f:
print(line.rstrip("\n"))Iterating the file object streams through a buffered reader and speaks universal newlines — \n, \r\n, and a lone \r all arrive as \n (open with newline='' only for csv). read().split('\n') slurps and mishandles CRLF; the last line without a newline still arrives.
CC
#include <stdio.h>
int main(void) {
FILE *f = fopen("app.log", "r");
if (f == NULL) {
perror("fopen");
return 1;
}
char line[256];
while (fgets(line, sizeof line, f) != NULL) {
fputs(line, stdout); /* keeps the trailing '\n' */
}
fclose(f);
return 0;
}fgets stores at most sizeof line - 1 bytes and keeps the '\n' — a line longer than the buffer arrives split across several calls. It returns NULL at EOF and on error; ferror(f) tells them apart. For unbounded lines use POSIX getline(&buf, &cap, f), which allocates.
C++C++
#include <fstream>
#include <iostream>
#include <string>
int main() {
std::ifstream in("app.log");
std::string line;
while (std::getline(in, line)) {
std::cout << line << '\n';
}
}std::getline strips the '\n' delimiter but leaves a '\r' from CRLF files — trim before exact comparisons. ifstreams buffer by default, and the returned stream converts to false at EOF; std::istringstream over a slurped std::string is the non-streaming alternative.
C#C#
using System.IO;
foreach (string line in File.ReadLines("app.log"))
{
Console.WriteLine(line);
}File.ReadLines is the lazy IEnumerable<string> — File.ReadAllLines() loads every line into an array first and looks nearly identical at the call site. ReadLines decodes UTF-8, splits on \n and \r\n, and never yields a phantom empty line after a trailing newline.
JvJava
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.stream.Stream;
public class ReadLines {
public static void main(String[] args) throws IOException {
try (Stream<String> lines = Files.lines(Path.of("app.log"))) {
lines.filter(line -> line.contains("ERROR"))
.forEach(System.out::println);
}
}
}Files.lines streams lazily and decodes UTF-8 by default — Files.readAllLines slurps a List<String> first. The stream keeps the file open, so try-with-resources is not optional: skipping it leaks the descriptor until GC. Java 11+ for Path.of.
SwSwift
import Foundation
@main
struct ReadLines {
static func main() async throws {
let url = URL(fileURLWithPath: "app.log")
for try await line in url.lines {
print(line)
}
}
}URL.lines (macOS 13 / iOS 16+) streams the file as an AsyncSequence of lines, and @main with an async main() makes the process await it — String(contentsOf:) + split is the slurping trap it replaces. On older runtimes, read Data chunks via FileHandle and split on \n yourself.
KtKotlin
import java.io.File
fun main() {
File("app.log").useLines { lines ->
lines.forEach(::println)
}
}useLines closes the handle when the block returns — the Sequence is lazy and single-shot, so consume it inside the block. readLines() is the array-slurping sibling; forEachLine { } is the inline shortcut over the same machinery.
RbRuby
File.foreach('app.log') { |line| puts line }foreach yields one line (newline included) at a time in constant memory — IO.readlines('app.log') materializes the whole array first. Call line.chomp when the trailing "\n" would pollute a comparison or a hash key.
ZigZig
const std = @import("std");
pub fn main() !void {
var file = try std.fs.cwd().openFile("app.log", .{});
defer file.close();
var buffered = std.io.bufferedReader(file.reader());
const reader = buffered.reader();
const stdout = std.io.getStdOut().writer();
while (try reader.readUntilDelimiterOrEofAlloc(std.heap.page_allocator, '\n', 1024 * 1024)) |line| {
defer std.heap.page_allocator.free(line);
try stdout.print("{s}\n", .{std.mem.trimRight(u8, line, "\r")});
}
}Stdlib only, and File has no newline-aware helper: bufferedReader wraps the fd, then readUntilDelimiterOrEofAlloc allocates each line without the delimiter and returns null at EOF (ending the while). A '\r' before the '\n' is yours to trim, and the max-size argument turns a newline-free binary blob into error.StreamTooLong instead of an unbounded allocation.