Packages

erlang common library

Current section

Files

Jump to
elib src eproperties.erl
Raw

src/eproperties.erl

%%%-------------------------------------------------------------------
%%% @author alking
%%% @copyright
%%% @doc
%%% 读取,编辑properties 文件
%%% 执行标准:https://en.wikipedia.org/wiki/.properties
%%% TODO:添加转义字符处理,添加形如 \uxxxx的unicode字符处理
%%% @end
%%%-------------------------------------------------------------------
-module(eproperties).
-include_lib("kernel/include/logger.hrl").
-define(ESCAPE_CHAR, $\\).
%% API
-export([
read/1,
write/2
]).
read(FilePath) ->
case file:open(FilePath, [read, binary]) of
{ok, IO} ->
read_i(IO, [], []);
Err ->
Err
end.
read_i(IO, Acc, LastLine) ->
case file:read_line(IO) of
{ok, Bin} ->
Line = lists:flatten(io_lib:format("~ts", [Bin])),
{Acc2, LastRec2} = read_acc(Line, Acc, LastLine),
read_i(IO, Acc2, LastRec2);
eof ->
Acc
end.
read_acc([$# | _], Acc, LastLine) -> {Acc, LastLine};
read_acc([$! | _], Acc, LastLine) -> {Acc, LastLine};
read_acc([], Acc, LastLine) -> {Acc, LastLine};
read_acc(Line, Acc, LastLine) ->
[Last | L] = lists:reverse(Line),
case Last == ?ESCAPE_CHAR of
true ->
{Acc, LastLine ++ lists:reverse(L)};
false ->
Line2 = LastLine ++ Line,
case parse_line(Line2, []) of
{error, _} ->
?LOG_ERROR("parse line ~ts error", [Line2]),
{Acc, []};
{K, V} ->
{[{K, V} | Acc], []}
end
end.
parse_line([$= | Left], Acc) -> {lists:reverse(Acc), Left};
parse_line([$: | Left], Acc) -> {lists:reverse(Acc), Left};
parse_line([], _) ->
{error, format_error};
parse_line([X | L], Acc) ->
parse_line(L, [X | Acc]).
write(File, PL) ->
Con = build_content(PL, []),
file:write_file(File, Con).
build_content([], Acc) -> lists:reverse(Acc);
build_content([{K, V} | L], Acc) ->
Bin = unicode:characters_to_binary(lists:flatten(io_lib:format("~ts=~ts~n", [K, V]))),
build_content(L, [Bin | Acc]).