Julia 文件读写完全指南(中文 + 实战)
“零成本、类型安全、高性能” —— Julia 的 I/O 系统是科学计算与大数据处理的基石
一、核心概念
| 类型 | 用途 |
|---|---|
IO | 抽象 I/O 流 |
IOStream | 文件流 |
IOBuffer | 内存流 |
open() | 打开文件 |
read(), write() | 读写 |
close() | 关闭 |
二、基本文本文件读写
1. 写入文件
# 方法1:open + write + close
open("output.txt", "w") do io
write(io, "Hello, Julia!\n")
write(io, "第二行内容\n")
end
# 方法2:do 块自动关闭
open("output.txt", "w") do f
println(f, "自动换行")
print(f, "不换行")
end
2. 读取文件
# 读取全部
content = read("output.txt", String)
println(content)
# 逐行读取
open("data.txt") do f
for line in eachline(f)
println("行: $line")
end
end
# 读取为数组
lines = readlines("data.txt")
三、文件模式
| 模式 | 含义 |
|---|---|
"r" | 读(默认) |
"w" | 写(覆盖) |
"a" | 追加 |
"r+" | 读写(保留内容) |
"w+" | 读写(覆盖) |
"a+" | 读写(追加) |
open("log.txt", "a") do f
println(f, "新日志: $(now())")
end
四、二进制读写(高性能!)
# 写入二进制
open("data.bin", "w") do f
write(f, Int32(42))
write(f, Float64(3.14))
write(f, [1, 2, 3, 4]) # 写入数组
end
# 读取二进制
open("data.bin", "r") do f
x = read(f, Int32)
y = read(f, Float64)
arr = read!(f, Vector{Int32}(undef, 4))
println(x, ", ", y, ", ", arr)
end
零拷贝:
read!直接写入预分配数组
五、内存流 IOBuffer(超实用!)
# 字符串 ↔ 流
buf = IOBuffer()
write(buf, "Hello")
write(buf, " World!")
s = String(take!(buf)) # "Hello World!"
# 复用缓冲区
buf = IOBuffer()
for i in 1:1000
print(buf, i, ",")
end
data = String(take!(buf))
六、文件路径操作(Filesystem)
using FilePathsBase # 可选:更强大路径操作
# 标准库
path = "data/output.txt"
dirname(path) # "data"
basename(path) # "output.txt"
splitext(path) # ("data/output", ".txt")
abspath(path) # 绝对路径
isfile(path) # 是否存在
isdir("data") # 是否目录
# 创建目录
mkpath("logs/2025/10")
# 遍历目录
for file in readdir("data"; join=true)
println(file)
end
七、CSV 文件读写(推荐 CSV.jl)
安装:
] add CSV DataFrames
using CSV, DataFrames
# 写入 CSV
df = DataFrame(
name = ["Alice", "Bob"],
age = [25, 30],
score = [95.5, 88.0]
)
CSV.write("students.csv", df)
# 读取 CSV
df2 = CSV.read("students.csv", DataFrame)
println(df2)
高级选项
CSV.read("data.csv", DataFrame;
types = Dict(:age => Int, :score => Float64),
dateformat = "yyyy-mm-dd",
missingstring = "NA"
)
八、JSON 文件读写(JSON.jl)
using JSON
# 写入
data = Dict(
"name" => "Julia",
"version" => 1.10,
"features" => ["fast", "dynamic", "scientific"]
)
open("config.json", "w") do f
JSON.print(f, data, 2) # 2空格缩进
end
# 读取
config = open("config.json") do f
JSON.parse(f)
end
九、临时文件与自动清理
using FilePathsBase
# 临时文件
mktemp() do path, io
write(io, "临时数据")
close(io)
# 自动删除 path
end
# 临时目录
mktempdir() do dir
path = p"$(dir)/data.txt"
write(path, "内容")
# 自动删除整个目录
end
十、文件压缩(CodecZlib)
using CodecZlib
# 写入 gzip
open("data.txt.gz", "w") do f
gz = GzipCompressorStream(f)
write(gz, "压缩内容")
close(gz)
end
# 读取 gzip
open("data.txt.gz", "r") do f
gz = GzipDecompressorStream(f)
content = read(gz, String)
println(content)
end
十一、性能优化技巧
1. 预分配 + read!
# 快:避免动态增长
open("large.bin", "r") do f
filesize = stat(f).size
data = Vector{UInt8}(undef, filesize)
read!(f, data)
end
2. 缓冲写入
open("big.txt", "w") do f
buf = IOBuffer()
for i in 1:1_000_000
print(buf, i, "\n")
if position(buf) > 1_000_000
write(f, take!(buf))
end
end
write(f, take!(buf))
end
十二、综合示例:日志系统
module Logger
using Dates
const LOG_FILE = "app.log"
function log(level, msg)
open(LOG_FILE, "a") do f
timestamp = Dates.format(now(), "yyyy-mm-dd HH:MM:SS")
println(f, "[$timestamp] [$level] $msg")
end
end
info(msg) = log("INFO", msg)
error(msg) = log("ERROR", msg)
end
# 使用
using .Logger
info("系统启动")
error("连接失败")
十三、综合示例:二进制数据序列化
struct Point
x::Float64
y::Float64
end
function save_points(filename, points::Vector{Point})
open(filename, "w") do f
write(f, Int32(length(points)))
for p in points
write(f, p.x)
write(f, p.y)
end
end
end
function load_points(filename)
open(filename, "r") do f
n = read(f, Int32)
points = Vector{Point}(undef, n)
for i in 1:n
x = read(f, Float64)
y = read(f, Float64)
points[i] = Point(x, y)
end
return points
end
end
十四、文件读写速查表
| 操作 | 语法 |
|---|---|
| 打开 | open("file", "r") do f ... end |
| 写入 | write(f, data) |
| 读取 | read(f, String) |
| 逐行 | eachline(f) |
| 二进制 | read!(f, array) |
| 关闭 | close(f)(do 块自动) |
| CSV | CSV.write("file.csv", df) |
| JSON | JSON.print(f, dict) |
| 临时文件 | mktemp() do path, io ... end |
十五、小练习(立即上手)
- 写函数
copy_file(src, dst)高效复制文件 - 实现
tail -f实时监控日志文件 - 将 CSV 文件转为 JSON
- 写一个
Config模块支持.ini文件 - 实现二进制配置文件读写(支持版本)
答案示例
# 1. 高效复制
function copy_file(src, dst)
open(src, "r") do in_f
open(dst, "w") do out_f
buf = Vector{UInt8}(undef, 1024*1024) # 1MB
while !eof(in_f)
n = readbytes!(in_f, buf)
write(out_f, @view buf[1:n])
end
end
end
end
# 2. tail -f
function tail_f(filename; interval=1.0)
open(filename, "r") do f
seekend(f)
while true
if !eof(f)
line = readline(f)
println(line)
end
sleep(interval)
end
end
end
# 3. CSV → JSON
using CSV, DataFrames, JSON
df = CSV.read("data.csv", DataFrame)
json_data = [Dict(pairs(row)) for row in eachrow(df)]
open("data.json", "w") do f
JSON.print(f, json_data, 2)
end
十六、常见错误与避坑
| 错误 | 正确做法 |
|---|---|
open("file") 忘记关闭 | 用 do 块 |
read(f) 读取大文件 | 用 read! + 预分配 |
println(f, data) 忘记换行 | println 自动换行 |
路径拼接 "data/" * file | 用 joinpath("data", file) |
| 编码问题 | 指定 encoding="UTF-8" |
恭喜!你已精通 Julia 文件读写!
现在你可以:
- 构建高性能数据管道
- 实现日志系统、配置管理
- 处理CSV/JSON/二进制任意格式
- 写出零拷贝 I/O 代码
下一站推荐
| 主题 | 为什么学 |
|---|---|
CSV.jl + DataFrames | 表格数据 |
Parquet.jl | 列式存储 |
JLD2.jl | Julia 原生二进制 |
SQLite.jl | 嵌入式数据库 |
HTTP.jl | 网络 I/O |
需要我:
- 写一个 高性能日志轮转器?
- 实现 JLD2 序列化(保存任意对象)?
- 构建 配置热重载系统?
- 演示 内存映射文件(
Mmap)?
随时告诉我!