QT串列埠助手(五):檔案操作
阿新 • • 發佈:2021-02-08
> 作者:zzssdd2
>
> E-mail:[email protected]
# 一、前言
開發環境:**Qt5.12.10 + MinGW**
> 功能
- 檔案的傳送
- 資料的儲存
> 知識點
- `QFile`類的使用
- `QTimer`類的使用
- 文字的轉碼與編碼識別
- `QPushButton`、`QProgressBar`控制元件的使用
![](https://img2020.cnblogs.com/blog/2193174/202102/2193174-20210207230758495-4911234.png)
# 二、功能實現
本章功能主要包含兩個方面,一是通過串列埠傳送選定的文字檔案,二是將接收的資料儲存為本地文字檔案。最後還有對[《QT串列埠助手(三):資料接收》](https://www.cnblogs.com/zzssdd2/p/14319615.html)章節內容進行一個補充擴充套件。
## 2.1、檔案開啟
當`選擇檔案`按鈕點選後,觸發點選訊號對應的槽函式,在槽函式中進行檔案的開啟與讀取:
```c++
/*選擇並開啟檔案*/
QString curPath = QDir::currentPath(); //系統當前目錄
QString dlgTitle = "開啟檔案"; //對話方塊標題
QString filter = "文字檔案(*.txt);;二進位制檔案(*.bin *.dat);;所有檔案(*.*)"; //檔案過濾器
QString filepath = QFileDialog::getOpenFileName(this,dlgTitle,curPath,filter);
QFileInfo fileinfo(filepath);
if (filepath.isEmpty())
{
QMessageBox::warning(this,"警告","檔案為空");
return;
}
//檔案路徑顯示到傳送框
ui->Send_TextEdit->clear();
ui->Send_TextEdit->appendPlainText(filepath);
QFile file(filepath);
if (!file.exists())
{
QMessageBox::warning(this,"警告","檔案不存在");
return;
}
if (!file.open(QIODevice::ReadOnly))
{
QMessageBox::warning(this,"警告","檔案開啟失敗");
return;
}
```
## 2.2、編碼判斷
因為應用程式預設使用的編碼為*UTF-8*,如果開啟*GBK*格式編碼的檔案就會亂碼,所以需要判斷檔案的編碼,如果不是UTF-8則需要對檔案進行編碼轉換。
```c++
/* 設定應用程式的編碼解碼器 */
QTextCodec *codec = QTextCodec::codecForName("UTF-8");
QTextCodec::setCodecForLocale(codec);
```
> - [static] QTextCodec *QTextCodec::codecForName(const char \*name)
>
> Searches all installed QTextCodec objects and returns the one which best matches *name*; the match is case-insensitive. Returns 0 if no codec matching the name *name* could be found.
>
> - [static] void QTextCodec::setCodecForLocale(QTextCodec **c*)
>
> Set the codec to *c*; this will be returned by codecForLocale(). If *c* is a null pointer, the codec is reset to the default.
>
> This might be needed for some applications that want to use their own mechanism for setting the locale.
>
> Warning: This function is not reentrant.
```c++
/* 判斷編碼 */
QTextCodec::ConverterState state;
QTextCodec *codec = QTextCodec::codecForName("UTF-8");
FileText = codec->toUnicode(data.constData(),data.size(),&state);
//若有無效字元則是GBK編碼
if (state.invalidChars > 0)
{
//轉碼後返回
FileText = QTextCodec::codecForName("GBK")->toUnicode(data);
}
else
{
FileText = data;
}
```
對檔案進行上述的處理後,如果是GBK編碼則也能夠正確的讀取了。
> - QString QTextCodec::toUnicode(const char \**input*, int *size*, QTextCodec::ConverterState **state* = nullptr) const
>
> Converts the first *size* characters from the *input* from the encoding of this codec to Unicode, and returns the result in a QString.
>
> The *state* of the convertor used is updated.
>
> - QString QTextCodec::toUnicode(const QByteArray &*a*) const
>
> Converts *a* from the encoding of this codec to Unicode, and returns the result in a QString.
![](https://img2020.cnblogs.com/blog/2193174/202102/2193174-20210207230717670-1399417024.png)
## 2.3、檔案讀取
檔案開啟後,需要對檔案型別進行判斷,然後進行檔案資料的讀取:
```c++
/*判斷檔案型別*/
int type = 0;
QMimeDatabase db;
QMimeType mime = db.mimeTypeForFile(filepath);
if (mime.name().startsWith("text/"))
{
type = 1; //文字檔案
}
else if (mime.name().startsWith("application/"))
{
type = 2; //二進位制檔案
}
```
> QMimeType QMimeDatabase::mimeTypeForFile(const QString&*fileName*, QMimeDatabase::MatchMode *mode* = MatchDefault) const
>
> Returns a MIME type for the file named *fileName* using *mode*.
>
> This is an overloaded function.
>
>
>
> QMimeType 類描述檔案或資料的型別,由 MIME 型別字串表示,獲取到檔案型別後接下來就知道應該使用什麼方法讀取檔案內容了。常見檔案型別如下:
>
> | 描述(startsWith) | 型別 | 示例 |
> | ---------------- | --------------------- | -------------------------------------------------------- |
> | text | 普通文字 | text/plain, text/html, text/css, text/javascript |
> | image | 影象檔案(包含動態gif) | image/gif, image/png, image/jpeg, image/bmp, image/webp |
> | audio | 音訊檔案 | audio/wav, audio/mpeg, audio/midi, audio/webm, audio/ogg |
> | video | 視訊檔案 | video/mp4, video/x-flv, video/webm, video/ogg |
> | application | 二進位制資料 | application/xml, application/pdf |
```c++
/*讀取檔案*/
switch(type)
{
case 1:
{
//QIODevice讀取普通文字
QByteArray data = file.readAll();
file.close();
if (data.isEmpty())
{
QMessageBox::information(this, "提示", "檔案內容空");
return;
}
/* 判斷編碼 */
}
break;
case 2:
{
int filelen = fileinfo.size();