Я хочу перебрать содержимое текстового файла, которое при анализе определяет, в какой новый файл необходимо записать (и каким должно быть его содержимое).
У меня есть рабочее решение (см. Код ниже), но я не знаю, является ли это очень оптимальным подходом. В частности, я хотел бы автоматически обрабатывать закрытие файлов даже в случае непредвиденной ошибки. Я пытался разобраться с этим делом, но, пожалуйста, см. Комментарий к коду:
Что, если здесь что-то пойдет не так, у нас все еще могут быть открытые файлы
государство верно?
Насколько я прочитал, закрытие файлов защищает от повреждения файла. Это верно? Каковы другие последствия отсутствия файлов?
Если я могу убедиться, что файлы не повреждены, я могу написать код, который может продолжить выполнение (возможно, с некоторыми ручными настройками в зависимости от того, что найдено в журналах отладки) вместо того, чтобы начинать все сначала.
Рабочий раствор ( см. Вместо jupyter-notebook ):
Вопрос зависимости
# Ensure an empty directory for the execution of this question's code
tmp_dir = "/tmp/stackoverflow-question-55012211"
rm(tmp_dir, force=true, recursive=true)
mkdir(tmp_dir)
# Write example ".fakeq" files.
# In my real life problem, they would be ".fastq" (see https://en.wikipedia.org/wiki/FASTQ_format)
# and sample would not be known at this stage, simplifying to keep things relevant to question
open("$(tmp_dir)/pool1.fakeq", "w") do f
write(f, "id1_sample1_ACGTA\n")
write(f, "id2_sample3_CGTACG\n")
write(f, "id3_sample2_GTACTAC\n")
write(f, "id4_sample1_TACGGTAC\n")
write(f, "id5_sample2_ACGTGTACG\n")
write(f, "id6_sample3_CGTATACGTA\n")
write(f, "id7_sample2_GTACCGTAC\n")
write(f, "id8_sample1_TACGGTAC\n")
write(f, "id9_sample1_ACGTGTA\n")
end
open("$(tmp_dir)/pool2.fakeq", "w") do f
write(f, "id10_sample2_ACGTAACGTA\n")
write(f, "id11_sample1_CGTACGCGTACG\n")
write(f, "id12_sample3_GTACTACGTACTAC\n")
write(f, "id13_sample2_TACGGTACTACGGTAC\n")
write(f, "id14_sample1_ACGTGTACGACGTGTACG\n")
write(f, "id15_sample3_CGTATACGTACGTATACGTA\n")
write(f, "id16_sample2_GTACCGTACGTACCGTAC\n")
write(f, "id17_sample1_TACGGTACTACGGTAC\n")
write(f, "id18_sample1_ACGTGTAACGTGTA\n")
end
# This array can be in the order of 10 - 20 elements long
csv_header = [
"identifier",
"sample_name",
"sequence",
"sequence_length"
]
# This array can be in the order of 25 - 50 elements long.
# In real-life problem, we know this list of samples up front
# and sample_name is calculated by matching an array of nucleotide
# 'barcode' sequences up against each sequence in the .fastq files
sample_names = [
"sample1",
"sample2",
"sample3"
]
# This array can be in the order of 4 - 12 elements long
# In real-life problem, we know this list of pools up front and each
# pool corresponds to a .fastq file mentioned above
pool_list = [
"pool1",
"pool2"
]
# I am creating a mapping here so that a file is written in a location
# dependent on the sample name
# What if something goes wrong here, we could still have files in open state right?
# If inside the try block below, then potentially some files will be attempted to be
# closed before being opened
sample_csv_mapping = Dict(
sample_name => open("$(tmp_dir)/$(sample_name).csv", "w")
for sample_name in sample_names
)
Главный блок
# An attempt to ensure that files are closed in case of error
try
# Initialises (overwrites) csv with header
for (sample, csv_stream) in sample_csv_mapping
write(csv_stream, join(csv_header, ","), "\n")
end
for pool in pool_list
# This automatically handles closing file upon error
open("$(tmp_dir)/$(pool).fakeq", "r") do f
lines = readlines(f)
for line in lines
identifier, sample_name, sequence = split(line, "_")
sequence_length = length(sequence)
csv_row = [
identifier,
sample_name,
sequence,
sequence_length
]
write(sample_csv_mapping[sample_name], join(csv_row, ","), "\n")
end
end
end
finally
println("Manually handle closing files whether upon successful run or upon error")
for (sample, csv_stream) in sample_csv_mapping
close(csv_stream)
end
end