2026-03-02 11:07:51 +08:00
# include "DataProcessWorkPool.h"
# include "MeasureAnalysisProjectModel.h"
2026-03-03 18:15:34 +08:00
# include "GlobalDefine.h"
2026-03-02 21:39:41 +08:00
# include "csv.h"
2026-03-03 18:15:34 +08:00
# include <QDir>
# include <QThreadPool>
2026-03-02 21:39:41 +08:00
# include <algorithm>
2026-03-03 18:15:34 +08:00
# include <fstream>
2026-03-02 21:39:41 +08:00
# include <memory>
2026-03-03 18:15:34 +08:00
# include <queue>
2026-03-02 21:39:41 +08:00
# include <sstream>
2026-03-03 18:15:34 +08:00
# include <string>
# include <vector>
2026-03-02 11:07:51 +08:00
using namespace DataProcessWorkPool ;
2026-03-02 18:56:21 +08:00
using namespace io ;
2026-03-02 11:07:51 +08:00
2026-03-02 21:39:41 +08:00
void ParticleDataTask : : SetAllChannelParticleDataFilename ( const QString & all_channel_particle_data_filename )
2026-03-02 11:07:51 +08:00
{
this - > _all_channel_particle_data_filename = all_channel_particle_data_filename ;
}
2026-03-02 21:39:41 +08:00
void ParticleDataTask : : SetFinishedNotifier ( QObject * finished_notifier , const char * finished_process , const QString & project_name )
2026-03-02 11:07:51 +08:00
{
this - > _finished_notifier = finished_notifier ;
this - > _finished_notifier_process = finished_process ;
this - > _project_name = project_name ;
}
2026-03-02 21:39:41 +08:00
const QString & ParticleDataTask : : GetAllChannelParticleDataFilename ( ) const
2026-03-02 11:07:51 +08:00
{
return this - > _all_channel_particle_data_filename ;
}
2026-03-02 21:39:41 +08:00
const QString & ParticleDataTask : : GetProjectName ( ) const
2026-03-02 11:07:51 +08:00
{
return this - > _project_name ;
}
2026-03-02 21:39:41 +08:00
const char * ParticleDataTask : : GetFinishedNotifierProcess ( ) const
2026-03-02 11:07:51 +08:00
{
return this - > _finished_notifier_process ;
}
2026-03-02 21:39:41 +08:00
QObject * ParticleDataTask : : GetFinishedNotifier ( ) const
2026-03-02 11:07:51 +08:00
{
return this - > _finished_notifier ;
}
2026-03-02 21:39:41 +08:00
bool ParticleDataTask : : IsValidSetWorkParameters ( ) const
2026-03-02 11:07:51 +08:00
{
2026-03-03 18:15:34 +08:00
return ( ! GetAllChannelParticleDataFilename ( ) . isEmpty ( ) ) & & ( ! GetProjectName ( ) . isEmpty ( ) ) ;
2026-03-02 11:07:51 +08:00
}
2026-03-02 21:39:41 +08:00
void ParticleDataTask : : StartTask ( )
2026-03-02 11:07:51 +08:00
{
QThreadPool : : globalInstance ( ) - > start ( this ) ;
}
2026-03-02 21:39:41 +08:00
void ParticleDataTask : : run ( )
2026-03-02 11:07:51 +08:00
{
if ( ! IsValidSetWorkParameters ( ) ) {
return ;
}
2026-03-03 18:15:34 +08:00
if ( ! processEveryChannelParticleData ( ) ) {
2026-03-02 11:07:51 +08:00
return ;
}
2026-03-03 18:15:34 +08:00
if ( ( GetFinishedNotifier ( ) ! = nullptr ) & & ( GetFinishedNotifierProcess ( ) ! = nullptr ) ) {
QMetaObject : : invokeMethod ( _finished_notifier , _finished_notifier_process , Qt : : QueuedConnection , Q_ARG ( QString , _project_name ) ) ;
}
2026-03-02 11:07:51 +08:00
}
2026-03-02 18:56:21 +08:00
void EveryChannelParticleDataSeparateTask : : SetResultDataDir ( const QString & result_data_dir )
{
this - > _result_data_dir = result_data_dir ;
}
const QString & EveryChannelParticleDataSeparateTask : : GetResultDataDir ( ) const
{
return this - > _result_data_dir ;
}
bool EveryChannelParticleDataSeparateTask : : IsValidSetWorkParameters ( ) const
{
2026-03-02 21:39:41 +08:00
return ( ! GetResultDataDir ( ) . isEmpty ( ) ) & & ParticleDataTask : : IsValidSetWorkParameters ( ) ;
2026-03-02 18:56:21 +08:00
}
2026-03-02 11:07:51 +08:00
bool EveryChannelParticleDataSeparateTask : : processEveryChannelParticleData ( )
{
bool ret_ok = true ;
const QString & result_data_output_dir_path = GetResultDataDir ( ) ;
QDir result_data_output_dir ( result_data_output_dir_path ) ;
result_data_output_dir . mkpath ( result_data_output_dir_path ) ;
const QString & all_channel_particle_data_filename = GetAllChannelParticleDataFilename ( ) ;
QMap < uint , QString > particle_data_filename_list ;
try {
QMap < uint , std : : shared_ptr < std : : ofstream > > ch_particle_data_of_list ;
2026-03-02 18:56:21 +08:00
std : : string board_id_str = QString ( QStringLiteral ( u " 板卡号 " ) ) . toStdString ( ) ;
std : : string channel_id_str = QString ( QStringLiteral ( u " 通道号 " ) ) . toStdString ( ) ;
std : : string address_str = QString ( QStringLiteral ( u " 道址 " ) ) . toStdString ( ) ;
std : : string time_str = QString ( QStringLiteral ( u " 时间计数 " ) ) . toStdString ( ) ;
2026-03-02 21:39:41 +08:00
// 使用更灵活的方式处理CSV文件, 忽略额外列
io : : CSVReader <
4 ,
io : : trim_chars < ' ' , ' \t ' > ,
io : : double_quote_escape < ' , ' , ' " ' > ,
io : : throw_on_overflow ,
2026-03-03 18:15:34 +08:00
io : : empty_line_comment >
reader ( QStrToSysPath ( all_channel_particle_data_filename ) ) ;
2026-03-02 21:39:41 +08:00
reader . read_header ( io : : ignore_extra_column , board_id_str , channel_id_str , address_str , time_str ) ;
2026-03-02 18:56:21 +08:00
uint board_id ;
uint channel_id ;
uint address ;
unsigned long long time ;
while ( reader . read_row ( board_id , channel_id , address , time ) ) {
2026-03-02 11:07:51 +08:00
// 板卡和通道号计算,通道号 = 板卡号 * 4 + 通道号
int channel_num = ( board_id ) * 4 + ( channel_id + 1 ) ;
QString particle_data_filename = result_data_output_dir . filePath ( QString ( " ParticleData_ch_%1.csv " ) . arg ( channel_num ) ) ;
if ( ! particle_data_filename_list . contains ( channel_num ) ) {
particle_data_filename_list . insert ( channel_num , particle_data_filename ) ;
}
2026-03-03 18:15:34 +08:00
if ( ! ch_particle_data_of_list . contains ( channel_num ) ) {
2026-03-02 11:07:51 +08:00
std : : shared_ptr < std : : ofstream > out (
2026-03-03 18:15:34 +08:00
new std : : ofstream ( QStrToSysPath ( particle_data_filename ) , std : : ios : : out | std : : ios : : app ) ,
[ ] ( std : : ofstream * p ) { p - > close ( ) ; } ) ;
2026-03-02 18:56:21 +08:00
* out < < QString ( QStringLiteral ( u " 板卡号,通道号,道址,时间计数 " ) ) . toStdString ( ) < < std : : endl ;
2026-03-03 18:15:34 +08:00
ch_particle_data_of_list . insert ( channel_num , out ) ;
2026-03-02 11:07:51 +08:00
}
auto ch_particle_data_of = ch_particle_data_of_list . value ( channel_num ) ;
2026-03-02 18:56:21 +08:00
* ch_particle_data_of < < board_id < < " , " < < channel_id < < " , " < < address < < " , " < < time < < std : : endl ;
2026-03-02 11:07:51 +08:00
}
} catch ( const std : : runtime_error & e ) {
QString error = QString ( QStringLiteral ( u " 处理%1发生运行时异常:%2 " ) ) . arg ( all_channel_particle_data_filename ) . arg ( e . what ( ) ) ;
LOG_ERROR ( error )
ret_ok = false ;
} catch ( const std : : exception & e ) {
QString error = QString ( QStringLiteral ( u " 处理%1异常:%2 " ) ) . arg ( all_channel_particle_data_filename ) . arg ( e . what ( ) ) ;
LOG_ERROR ( error )
ret_ok = false ;
} catch ( . . . ) {
QString error = QString ( QStringLiteral ( u " 处理%1未知异常. " ) ) . arg ( all_channel_particle_data_filename ) ;
LOG_ERROR ( error )
ret_ok = false ;
}
const QString & project_name = GetProjectName ( ) ;
MeasureAnalysisProjectModel * project_model = MeasureAnalysisProjectModelList : : GetProjectModel ( project_name ) ;
if ( project_model = = nullptr ) {
ret_ok = false ;
}
for ( auto it = particle_data_filename_list . begin ( ) ; it ! = particle_data_filename_list . end ( ) ; + + it ) {
project_model - > SetChannelParticleDataFilename ( it . key ( ) , it . value ( ) ) ;
}
2026-03-03 18:15:34 +08:00
2026-03-02 11:07:51 +08:00
return ret_ok ;
}
2026-03-03 18:15:34 +08:00
void EveryChannelParticleCountDataTask : : SetAllChannelCountResultDir ( const QString & dir_path )
2026-03-02 18:56:21 +08:00
{
this - > _all_ch_count_dir = dir_path ;
}
2026-03-03 18:15:34 +08:00
const QString & EveryChannelParticleCountDataTask : : GetAllChannelCountResultDir ( ) const
2026-03-02 18:56:21 +08:00
{
return this - > _all_ch_count_dir ;
}
2026-03-03 18:15:34 +08:00
void EveryChannelParticleCountDataTask : : SetEveryChannelCountResultDir ( const QString & dir_path )
2026-03-02 18:56:21 +08:00
{
this - > _every_ch_count_dir = dir_path ;
}
2026-03-03 18:15:34 +08:00
const QString & EveryChannelParticleCountDataTask : : GetEveryChannelCountResultDir ( ) const
2026-03-02 18:56:21 +08:00
{
return this - > _every_ch_count_dir ;
}
bool EveryChannelParticleCountDataTask : : IsValidSetWorkParameters ( ) const
{
2026-03-03 18:15:34 +08:00
return ( ! GetAllChannelCountResultDir ( ) . isEmpty ( ) ) & & ( ! GetEveryChannelCountResultDir ( ) . isEmpty ( ) ) & & ParticleDataTask : : IsValidSetWorkParameters ( ) ;
2026-03-02 18:56:21 +08:00
}
2026-03-02 11:07:51 +08:00
bool EveryChannelParticleCountDataTask : : processEveryChannelParticleData ( )
{
bool ret_ok = true ;
2026-03-02 18:56:21 +08:00
const QString & all_ch_count_dir = GetAllChannelCountResultDir ( ) ;
const QString & every_ch_count_dir = GetEveryChannelCountResultDir ( ) ;
2026-03-03 18:15:34 +08:00
2026-03-02 18:56:21 +08:00
QDir all_ch_count_output_dir ( all_ch_count_dir ) ;
all_ch_count_output_dir . mkpath ( all_ch_count_dir ) ;
2026-03-03 18:15:34 +08:00
2026-03-02 18:56:21 +08:00
QDir every_ch_count_output_dir ( every_ch_count_dir ) ;
every_ch_count_output_dir . mkpath ( every_ch_count_dir ) ;
2026-03-02 11:07:51 +08:00
const QString & all_channel_particle_data_filename = GetAllChannelParticleDataFilename ( ) ;
2026-03-02 18:56:21 +08:00
QMap < uint , QString > particle_count_filename_list ;
QString all_channel_total_count_filename ;
2026-03-02 11:07:51 +08:00
try {
2026-03-02 18:56:21 +08:00
// 统计每个通道的粒子计数(相同板卡号通道号相同道址)
QMap < uint , QMap < uint , uint > > channel_address_counts ; // 通道号 -> 地址 -> 计数
2026-03-03 18:15:34 +08:00
2026-03-02 18:56:21 +08:00
// 统计所有通道的粒子计数(不同板卡号通道号相同道址)
QMap < uint , uint > all_channel_address_counts ; // 地址 -> 计数
2026-03-03 18:15:34 +08:00
2026-03-02 18:56:21 +08:00
std : : string board_id_str = QString ( QStringLiteral ( u " 板卡号 " ) ) . toStdString ( ) ;
std : : string channel_id_str = QString ( QStringLiteral ( u " 通道号 " ) ) . toStdString ( ) ;
std : : string address_str = QString ( QStringLiteral ( u " 道址 " ) ) . toStdString ( ) ;
std : : string time_str = QString ( QStringLiteral ( u " 时间计数 " ) ) . toStdString ( ) ;
2026-03-03 18:15:34 +08:00
2026-03-02 21:39:41 +08:00
// 使用更灵活的方式处理CSV文件, 忽略额外列
io : : CSVReader <
4 ,
io : : trim_chars < ' ' , ' \t ' > ,
io : : double_quote_escape < ' , ' , ' " ' > ,
io : : throw_on_overflow ,
2026-03-03 18:15:34 +08:00
io : : empty_line_comment >
reader ( QStrToSysPath ( all_channel_particle_data_filename ) ) ;
2026-03-02 21:39:41 +08:00
reader . read_header ( io : : ignore_extra_column , board_id_str , channel_id_str , address_str , time_str ) ;
2026-03-02 18:56:21 +08:00
uint board_id ;
uint channel_id ;
uint address ;
unsigned long long time ;
while ( reader . read_row ( board_id , channel_id , address , time ) ) {
2026-03-02 11:07:51 +08:00
// 板卡和通道号计算,通道号 = 板卡号 * 4 + 通道号
int channel_num = ( board_id ) * 4 + ( channel_id + 1 ) ;
2026-03-03 18:15:34 +08:00
2026-03-02 18:56:21 +08:00
// 统计每个通道的粒子计数
if ( ! channel_address_counts . contains ( channel_num ) ) {
channel_address_counts [ channel_num ] = QMap < uint , uint > ( ) ;
2026-03-02 11:07:51 +08:00
}
2026-03-02 18:56:21 +08:00
channel_address_counts [ channel_num ] [ address ] + + ;
2026-03-03 18:15:34 +08:00
2026-03-02 18:56:21 +08:00
// 统计所有通道的粒子计数
all_channel_address_counts [ address ] + + ;
}
2026-03-03 18:15:34 +08:00
2026-03-02 18:56:21 +08:00
// 写入每个通道的粒子计数数据(优化:使用一次打开文件,批量写入)
QMap < uint , std : : shared_ptr < std : : ofstream > > channel_file_streams ;
2026-03-03 18:15:34 +08:00
2026-03-02 18:56:21 +08:00
// 预创建所有通道的文件流
for ( auto channel_it = channel_address_counts . begin ( ) ; channel_it ! = channel_address_counts . end ( ) ; + + channel_it ) {
uint channel_num = channel_it . key ( ) ;
QString count_data_filename = every_ch_count_output_dir . filePath ( QString ( " ParticleCountData_ch_%1.csv " ) . arg ( channel_num ) ) ;
particle_count_filename_list . insert ( channel_num , count_data_filename ) ;
2026-03-03 18:15:34 +08:00
2026-03-02 18:56:21 +08:00
// 创建文件流
2026-03-03 18:15:34 +08:00
std : : shared_ptr < std : : ofstream > out ( new std : : ofstream ( QStrToSysPath ( count_data_filename ) ) ) ;
2026-03-02 18:56:21 +08:00
channel_file_streams [ channel_num ] = out ;
* out < < QString ( QStringLiteral ( u " 道址 " ) ) . toStdString ( ) < < " , " < < QString ( QStringLiteral ( u " 计数 " ) ) . toStdString ( ) < < std : : endl ;
}
2026-03-03 18:15:34 +08:00
2026-03-02 18:56:21 +08:00
// 批量写入数据
for ( auto channel_it = channel_address_counts . begin ( ) ; channel_it ! = channel_address_counts . end ( ) ; + + channel_it ) {
uint channel_num = channel_it . key ( ) ;
const QMap < uint , uint > & address_counts = channel_it . value ( ) ;
auto out_stream = channel_file_streams [ channel_num ] ;
2026-03-03 18:15:34 +08:00
2026-03-02 18:56:21 +08:00
for ( auto address_it = address_counts . begin ( ) ; address_it ! = address_counts . end ( ) ; + + address_it ) {
uint address = address_it . key ( ) ;
uint count = address_it . value ( ) ;
* out_stream < < address < < " , " < < count < < std : : endl ;
2026-03-02 11:07:51 +08:00
}
}
2026-03-03 18:15:34 +08:00
2026-03-02 18:56:21 +08:00
// 文件流会在shared_ptr析构时自动关闭
channel_file_streams . clear ( ) ;
2026-03-03 18:15:34 +08:00
2026-03-02 18:56:21 +08:00
// 写入所有通道的粒子计数数据
all_channel_total_count_filename = all_ch_count_output_dir . filePath ( " AllChannelParticleTotalCountData.csv " ) ;
2026-03-03 18:15:34 +08:00
std : : ofstream all_channel_out ( QStrToSysPath ( all_channel_total_count_filename ) ) ;
2026-03-02 18:56:21 +08:00
all_channel_out < < QString ( QStringLiteral ( u " 道址 " ) ) . toStdString ( ) < < " , " < < QString ( QStringLiteral ( u " 计数 " ) ) . toStdString ( ) < < std : : endl ;
2026-03-03 18:15:34 +08:00
2026-03-02 18:56:21 +08:00
for ( auto address_it = all_channel_address_counts . begin ( ) ; address_it ! = all_channel_address_counts . end ( ) ; + + address_it ) {
uint address = address_it . key ( ) ;
uint count = address_it . value ( ) ;
all_channel_out < < address < < " , " < < count < < std : : endl ;
}
all_channel_out . close ( ) ;
2026-03-03 18:15:34 +08:00
2026-03-02 11:07:51 +08:00
} catch ( const std : : runtime_error & e ) {
QString error = QString ( QStringLiteral ( u " 处理%1发生运行时异常:%2 " ) ) . arg ( all_channel_particle_data_filename ) . arg ( e . what ( ) ) ;
LOG_ERROR ( error )
ret_ok = false ;
} catch ( const std : : exception & e ) {
QString error = QString ( QStringLiteral ( u " 处理%1异常:%2 " ) ) . arg ( all_channel_particle_data_filename ) . arg ( e . what ( ) ) ;
LOG_ERROR ( error )
ret_ok = false ;
} catch ( . . . ) {
2026-03-02 18:56:21 +08:00
QString error = QString ( QStringLiteral ( u " 处理%1未知异常. " ) . arg ( all_channel_particle_data_filename ) ) ;
2026-03-02 11:07:51 +08:00
LOG_ERROR ( error )
ret_ok = false ;
}
const QString & project_name = GetProjectName ( ) ;
MeasureAnalysisProjectModel * project_model = MeasureAnalysisProjectModelList : : GetProjectModel ( project_name ) ;
if ( project_model = = nullptr ) {
ret_ok = false ;
2026-03-02 18:56:21 +08:00
} else {
// 更新项目模型中的通道粒子计数数据文件名
for ( auto it = particle_count_filename_list . begin ( ) ; it ! = particle_count_filename_list . end ( ) ; + + it ) {
project_model - > SetChannelParticleCountDataFilename ( it . key ( ) , it . value ( ) ) ;
}
// 更新项目模型中的所有通道粒子总计数数据文件名
project_model - > SetAllChannelParticleTotalCountDataFilename ( all_channel_total_count_filename ) ;
2026-03-02 11:07:51 +08:00
}
return ret_ok ;
}
2026-03-02 21:39:41 +08:00
////////////////////////////////////////////////////////////////////////////////////
void ParticleDataSortTask : : SetSortedResultDir ( const QString & sorted_result_dir )
{
this - > _sorted_result_dir = sorted_result_dir ;
}
const QString & ParticleDataSortTask : : GetSortedResultDir ( ) const
{
return this - > _sorted_result_dir ;
}
bool ParticleDataSortTask : : IsValidSetWorkParameters ( ) const
{
return ( ! GetSortedResultDir ( ) . isEmpty ( ) ) & & ParticleDataTask : : IsValidSetWorkParameters ( ) ;
}
struct CsvRow {
uint board_id ;
uint channel_id ;
uint address ;
unsigned long long time ;
size_t chunk_index ;
2026-03-03 18:15:34 +08:00
bool operator < ( const CsvRow & other ) const
{
2026-03-02 21:39:41 +08:00
return time > other . time ;
}
} ;
2026-03-03 18:15:34 +08:00
std : : vector < std : : string > splitFile ( const std : : string & input_file , size_t chunk_size )
{
2026-03-02 21:39:41 +08:00
std : : vector < std : : string > chunks ;
2026-03-03 18:15:34 +08:00
2026-03-02 21:39:41 +08:00
try {
std : : string board_id_str = QString ( QStringLiteral ( u " 板卡号 " ) ) . toStdString ( ) ;
std : : string channel_id_str = QString ( QStringLiteral ( u " 通道号 " ) ) . toStdString ( ) ;
std : : string address_str = QString ( QStringLiteral ( u " 道址 " ) ) . toStdString ( ) ;
std : : string time_str = QString ( QStringLiteral ( u " 时间计数 " ) ) . toStdString ( ) ;
2026-03-03 18:15:34 +08:00
io : : CSVReader <
4 ,
io : : trim_chars < ' ' , ' \t ' > ,
io : : double_quote_escape < ' , ' , ' " ' > ,
io : : throw_on_overflow ,
io : : empty_line_comment
> reader ( input_file ) ;
2026-03-02 21:39:41 +08:00
reader . read_header ( io : : ignore_extra_column , board_id_str , channel_id_str , address_str , time_str ) ;
2026-03-03 18:15:34 +08:00
2026-03-02 21:39:41 +08:00
int chunkIndex = 0 ;
2026-03-03 18:15:34 +08:00
2026-03-02 21:39:41 +08:00
while ( true ) {
std : : vector < CsvRow > rows ;
size_t currentSize = 0 ;
2026-03-03 18:15:34 +08:00
2026-03-02 21:39:41 +08:00
uint board_id ;
uint channel_id ;
uint address ;
unsigned long long time ;
2026-03-03 18:15:34 +08:00
2026-03-02 21:39:41 +08:00
while ( reader . read_row ( board_id , channel_id , address , time ) ) {
CsvRow row ;
row . board_id = board_id ;
row . channel_id = channel_id ;
row . address = address ;
row . time = time ;
2026-03-03 18:15:34 +08:00
2026-03-02 21:39:41 +08:00
// Estimate row size
2026-03-03 18:15:34 +08:00
currentSize + = std : : to_string ( board_id ) . size ( ) + std : : to_string ( channel_id ) . size ( ) + std : : to_string ( address ) . size ( ) + std : : to_string ( time ) . size ( ) + 4 ; // +4 for commas
if ( currentSize > chunk_size & & ! rows . empty ( ) ) {
2026-03-02 21:39:41 +08:00
break ;
}
2026-03-03 18:15:34 +08:00
2026-03-02 21:39:41 +08:00
rows . push_back ( row ) ;
}
2026-03-03 18:15:34 +08:00
if ( rows . empty ( ) )
break ;
2026-03-02 21:39:41 +08:00
std : : sort ( rows . begin ( ) , rows . end ( ) , [ ] ( const CsvRow & a , const CsvRow & b ) {
return a . time < b . time ;
} ) ;
2026-03-03 18:15:34 +08:00
std : : string chunkFile = input_file + " .chunk " + std : : to_string ( chunkIndex ) ;
2026-03-02 21:39:41 +08:00
std : : ofstream outFile ( chunkFile ) ;
for ( const auto & row : rows ) {
outFile < < row . board_id < < " , " < < row . channel_id < < " , " < < row . address < < " , " < < row . time < < " \n " ;
}
outFile . close ( ) ;
2026-03-03 18:15:34 +08:00
2026-03-02 21:39:41 +08:00
chunks . push_back ( chunkFile ) ;
chunkIndex + + ;
}
} catch ( const std : : exception & e ) {
// Handle exception
}
2026-03-03 18:15:34 +08:00
2026-03-02 21:39:41 +08:00
return chunks ;
}
2026-03-03 18:15:34 +08:00
void mergeChunks ( const std : : vector < std : : string > & chunks , const std : : string & output_file )
{
2026-03-02 21:39:41 +08:00
std : : vector < std : : unique_ptr < io : : CSVReader < 4 > > > chunkReaders ;
std : : priority_queue < CsvRow > minHeap ;
for ( const auto & chunk : chunks ) {
auto reader = std : : make_unique < io : : CSVReader < 4 > > ( chunk ) ;
chunkReaders . push_back ( std : : move ( reader ) ) ;
}
2026-03-03 18:15:34 +08:00
2026-03-02 21:39:41 +08:00
for ( size_t i = 0 ; i < chunkReaders . size ( ) ; i + + ) {
uint board_id ;
uint channel_id ;
uint address ;
unsigned long long time ;
2026-03-03 18:15:34 +08:00
2026-03-02 21:39:41 +08:00
if ( chunkReaders [ i ] - > read_row ( board_id , channel_id , address , time ) ) {
CsvRow row ;
row . board_id = board_id ;
row . channel_id = channel_id ;
row . address = address ;
row . time = time ;
row . chunk_index = i ;
minHeap . push ( row ) ;
}
}
2026-03-03 18:15:34 +08:00
2026-03-02 21:39:41 +08:00
std : : string board_id_str = QString ( QStringLiteral ( u " 板卡号 " ) ) . toStdString ( ) ;
std : : string channel_id_str = QString ( QStringLiteral ( u " 通道号 " ) ) . toStdString ( ) ;
std : : string address_str = QString ( QStringLiteral ( u " 道址 " ) ) . toStdString ( ) ;
std : : string time_str = QString ( QStringLiteral ( u " 时间计数 " ) ) . toStdString ( ) ;
2026-03-03 18:15:34 +08:00
std : : ofstream outFile ( output_file ) ;
2026-03-02 21:39:41 +08:00
outFile < < board_id_str < < " , " < < channel_id_str < < " , " < < address_str < < " , " < < time_str < < " \n " ;
2026-03-03 18:15:34 +08:00
2026-03-02 21:39:41 +08:00
while ( ! minHeap . empty ( ) ) {
CsvRow current = minHeap . top ( ) ;
minHeap . pop ( ) ;
outFile < < current . board_id < < " , " < < current . channel_id < < " , " < < current . address < < " , " < < current . time < < " \n " ;
2026-03-03 18:15:34 +08:00
2026-03-02 21:39:41 +08:00
size_t chunk_index = current . chunk_index ;
if ( chunkReaders [ chunk_index ] ) {
uint board_id ;
uint channel_id ;
uint address ;
unsigned long long time ;
2026-03-03 18:15:34 +08:00
2026-03-02 21:39:41 +08:00
if ( chunkReaders [ chunk_index ] - > read_row ( board_id , channel_id , address , time ) ) {
CsvRow row ;
row . board_id = board_id ;
row . channel_id = channel_id ;
row . address = address ;
row . time = time ;
row . chunk_index = chunk_index ;
minHeap . push ( row ) ;
} else {
chunkReaders [ chunk_index ] . reset ( ) ;
}
}
}
2026-03-03 18:15:34 +08:00
2026-03-02 21:39:41 +08:00
outFile . close ( ) ;
for ( const auto & chunk : chunks ) {
std : : remove ( chunk . c_str ( ) ) ;
}
}
bool ParticleDataSortTask : : processEveryChannelParticleData ( )
{
bool ret_ok = true ;
const QString & sorted_result_dir = GetSortedResultDir ( ) ;
QDir sorted_result_output_dir ( sorted_result_dir ) ;
sorted_result_output_dir . mkpath ( sorted_result_dir ) ;
const QString & all_channel_particle_data_filename = GetAllChannelParticleDataFilename ( ) ;
QString sorted_output_filename = sorted_result_output_dir . filePath ( " SortedParticleData.csv " ) ;
try {
const size_t CHUNK_SIZE = 100 * 1024 * 1024 ; // 100MB chunks
2026-03-03 18:15:34 +08:00
std : : vector < std : : string > chunks = splitFile ( QStrToSysPath ( all_channel_particle_data_filename ) , CHUNK_SIZE ) ;
2026-03-02 21:39:41 +08:00
if ( chunks . empty ( ) ) {
2026-03-03 18:15:34 +08:00
std : : ifstream in_file ( QStrToSysPath ( all_channel_particle_data_filename ) ) ;
std : : ofstream out_file ( QStrToSysPath ( sorted_output_filename ) ) ;
2026-03-02 21:39:41 +08:00
std : : string line ;
2026-03-03 18:15:34 +08:00
while ( std : : getline ( in_file , line ) ) {
out_file < < line < < " \n " ;
2026-03-02 21:39:41 +08:00
}
2026-03-03 18:15:34 +08:00
in_file . close ( ) ;
out_file . close ( ) ;
2026-03-02 21:39:41 +08:00
} else {
2026-03-03 18:15:34 +08:00
mergeChunks ( chunks , QStrToSysPath ( sorted_output_filename ) ) ;
2026-03-02 21:39:41 +08:00
}
2026-03-03 18:15:34 +08:00
2026-03-02 21:39:41 +08:00
} catch ( const std : : exception & e ) {
QString error = QString ( QStringLiteral ( u " 处理%1异常:%2 " ) ) . arg ( all_channel_particle_data_filename ) . arg ( e . what ( ) ) ;
LOG_ERROR ( error )
ret_ok = false ;
} catch ( . . . ) {
QString error = QString ( QStringLiteral ( u " 处理%1未知异常. " ) ) . arg ( all_channel_particle_data_filename ) ;
LOG_ERROR ( error )
ret_ok = false ;
}
const QString & project_name = GetProjectName ( ) ;
MeasureAnalysisProjectModel * project_model = MeasureAnalysisProjectModelList : : GetProjectModel ( project_name ) ;
if ( project_model = = nullptr ) {
ret_ok = false ;
} else {
project_model - > SetSortedParticleDataFilename ( sorted_output_filename ) ;
}
return ret_ok ;
}