假定有一個文件test.txt
包含字符串'test'
。Python中截斷(0)後的文件中的垃圾
現在,請考慮以下Python代碼:
f = open('test', 'r+')
f.read()
f.truncate(0)
f.write('passed')
f.flush();
現在我希望test.txt
包含'passed'
現在,但也有一些額外奇怪的符號!
更新:truncate後刷新沒有幫助。
假定有一個文件test.txt
包含字符串'test'
。Python中截斷(0)後的文件中的垃圾
現在,請考慮以下Python代碼:
f = open('test', 'r+')
f.read()
f.truncate(0)
f.write('passed')
f.flush();
現在我希望test.txt
包含'passed'
現在,但也有一些額外奇怪的符號!
更新:truncate後刷新沒有幫助。
這是因爲truncate不改變流的位置。
當您將文件read()
移動到最後。因此,連續的write
將從該位置寫入文件。 但是,當您撥打flush()
時,它似乎不僅嘗試將緩衝區寫入文件,而且還會執行一些錯誤檢查並修復當前文件位置。在truncate(0)
之後調用Flush()
時,不寫任何內容(緩衝區爲空),然後檢查文件大小並將該位置置於第一個適用位置(即0
)。
UPDATE
Python的文件的功能不只是圍繞着C標準庫等價的包裝,但我們知道的C函數有助於瞭解什麼是更精確地發生。
尋道指針的值不被呼叫改性與ftruncate()。
如果流指向一個輸入流或其中最近一次操作是輸入的更新流,該流被刷新,如果它是可搜索,是不是已經在年底-of文件。刷新輸入流會丟棄任何緩衝的輸入並調整文件指針,以便在最後一次讀取後下一個輸入操作訪問該字節。
這意味着如果您在之前truncate
它沒有效果。我查了一下,結果如此。
但是用於使flush
後truncate
:
如果流點到輸出流或其中的最近操作不是輸入的更新流,fflush()導致該流是任何未寫入數據寫入文件,並且底層文件的st_ctime和st_mtime字段被標記爲更新。
當解釋輸出流時沒有輸入上一個操作時,手冊頁沒有提到seek指針。 (在這裏我們最後的操作truncate
)
更新2
我發現了一些在Python源代碼:Python-3.2.2\Modules\_io\fileio.c:837
#ifdef HAVE_FTRUNCATE
static PyObject *
fileio_truncate(fileio *self, PyObject *args)
{
PyObject *posobj = NULL; /* the new size wanted by the user */
#ifndef MS_WINDOWS
Py_off_t pos;
#endif
...
#ifdef MS_WINDOWS
/* MS _chsize doesn't work if newsize doesn't fit in 32 bits,
so don't even try using it. */
{
PyObject *oldposobj, *tempposobj;
HANDLE hFile;
////// THIS LINE //////////////////////////////////////////////////////////////
/* we save the file pointer position */
oldposobj = portable_lseek(fd, NULL, 1);
if (oldposobj == NULL) {
Py_DECREF(posobj);
return NULL;
}
/* we then move to the truncation position */
...
/* Truncate. Note that this may grow the file! */
...
////// AND THIS LINE //////////////////////////////////////////////////////////
/* we restore the file pointer position in any case */
tempposobj = portable_lseek(fd, oldposobj, 0);
Py_DECREF(oldposobj);
if (tempposobj == NULL) {
Py_DECREF(posobj);
return NULL;
}
Py_DECREF(tempposobj);
}
#else
...
#endif /* HAVE_FTRUNCATE */
看那兩行我表示(///// This Line /////
)。如果您的平臺是Windows,那麼它將保存位置並在截斷後將其返回。
令我吃驚的是,Python 3.2.2函數中的大多數flush
函數或者什麼也沒做,或者根本沒有調用fflush
C函數。 3.2.2截斷部分也很沒有記錄。但是,我確實在Python 2.7.2源代碼中找到了一些有趣的東西。首先,我在truncate
實施來找到這Python-2.7.2\Objects\fileobject.c:812
:
/* Get current file position. If the file happens to be open for
* update and the last operation was an input operation, C doesn't
* define what the later fflush() will do, but we promise truncate()
* won't change the current position (and fflush() *does* change it
* then at least on Windows). The easiest thing is to capture
* current pos now and seek back to it at the end.
*/
因此,要概括所有,我覺得這是一個完全依賴於平臺的事情。我檢查了用於Windows x64的默認Python 3.2.2,並得到了與您相同的結果。不知道* nixes上發生了什麼。
截斷不會更改文件位置。
還要注意的是,即使文件在讀取和寫入中打開,您也不能在兩種操作類型之間切換(例如,需要查找操作才能從讀取轉換爲寫入或反之亦然)。
我期待下面是你的意思是寫代碼:
open('test.txt').read()
open('test.txt', 'w').write('passed')
是啊,這是真的,truncate()
不動的位置,但他說,很簡單的死亡:
f.read()
f.seek(0)
f.truncate(0)
f.close()
這是完美的工作;)
據我所知,運行'truncate(0)'只需將文件大小設置爲0字節,並將文件指針移回到緩衝區的開始。在刷新之前寫入流時,緩衝區的狀態是未定義的。在刷新時,可能會從該緩衝區中顯示垃圾數據。我應用的一般規則是,只要您嘗試*刪除*任何內容,或者在繼續之前需要確保文件處於特定狀態時,您都應該刷新。 – Polynomial
關閉文件怎麼辦? – joaquin
@Polynomial flush也不起作用,我誤會了...... – Beginner